mirror of
https://github.com/actions/publish-action.git
synced 2026-01-09 03:28:25 +08:00
Implement the "publish-action" action
This commit is contained in:
103
src/api-utils.ts
Normal file
103
src/api-utils.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import * as core from '@actions/core';
|
||||
import { context } from '@actions/github';
|
||||
import { GitHub } from '@actions/github/lib/utils';
|
||||
|
||||
interface GitRef {
|
||||
ref: string;
|
||||
node_id: string;
|
||||
url: string;
|
||||
object: {
|
||||
type: string;
|
||||
sha: string;
|
||||
url: string;
|
||||
};
|
||||
}
|
||||
|
||||
async function findTag(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<GitRef | null> {
|
||||
try {
|
||||
const { data: foundTag } = await octokitClient.git.getRef({
|
||||
...context.repo,
|
||||
ref: `tags/${tag}`
|
||||
});
|
||||
|
||||
return foundTag;
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
return null;
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getTagSHA(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<string> {
|
||||
const foundTag = await findTag(tag, octokitClient);
|
||||
if (!foundTag) {
|
||||
throw new Error(
|
||||
`The '${tag}' tag does not exist in the remote repository`
|
||||
);
|
||||
}
|
||||
|
||||
return foundTag.object.sha;
|
||||
}
|
||||
|
||||
export async function validateIfReleaseIsPublished(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { data: foundRelease } = await octokitClient.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag,
|
||||
});
|
||||
|
||||
if (foundRelease.prerelease){
|
||||
throw new Error(
|
||||
`The '${foundRelease.name}' release is marked as pre-release. Updating tags for pre-release is not supported`
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
throw new Error(
|
||||
`No GitHub release found for the ${tag} tag`
|
||||
);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateTag(
|
||||
sourceTag: string,
|
||||
targetTag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<void> {
|
||||
const sourceTagSHA = await getTagSHA(sourceTag, octokitClient);
|
||||
const foundTargetTag = await findTag(targetTag, octokitClient);
|
||||
const refName = `tags/${targetTag}`;
|
||||
|
||||
if (foundTargetTag) {
|
||||
core.info(`Updating the '${targetTag}' tag to point to the '${sourceTag}' tag`);
|
||||
|
||||
await octokitClient.git.updateRef({
|
||||
...context.repo,
|
||||
ref: refName,
|
||||
sha: sourceTagSHA,
|
||||
force: true
|
||||
});
|
||||
} else {
|
||||
core.info(`Creating the '${targetTag}' tag from the '${sourceTag}' tag`);
|
||||
|
||||
await octokitClient.git.createRef({
|
||||
...context.repo,
|
||||
ref: `refs/${refName}`,
|
||||
sha: sourceTagSHA
|
||||
});
|
||||
}
|
||||
}
|
||||
26
src/main.ts
Normal file
26
src/main.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import { updateTag, validateIfReleaseIsPublished } from './api-utils';
|
||||
import { validateSemverVersionFromTag, getMajorTagFromFullTag } from './version-utils';
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
const token = core.getInput('token');
|
||||
const octokitClient = github.getOctokit(token);
|
||||
const sourceTagName = core.getInput('source-tag');
|
||||
|
||||
validateSemverVersionFromTag(sourceTagName);
|
||||
|
||||
await validateIfReleaseIsPublished(sourceTagName, octokitClient);
|
||||
|
||||
const majorTag = getMajorTagFromFullTag(sourceTagName);
|
||||
await updateTag(sourceTagName, majorTag, octokitClient);
|
||||
|
||||
core.setOutput('major-tag', majorTag);
|
||||
core.info(`The '${majorTag}' major tag now points to the '${sourceTagName}' tag`);
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
25
src/version-utils.ts
Normal file
25
src/version-utils.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import semverParse from 'semver/functions/parse';
|
||||
import SemVer from 'semver/classes/semver';
|
||||
|
||||
export function isStableSemverVersion(version: SemVer): boolean {
|
||||
return version.prerelease.length === 0
|
||||
}
|
||||
|
||||
export function getMajorTagFromFullTag(fullTag: string): string {
|
||||
return fullTag.split('.')[0];
|
||||
}
|
||||
|
||||
export function validateSemverVersionFromTag(tag: string): void {
|
||||
const semverVersion = semverParse(tag);
|
||||
if (!semverVersion) {
|
||||
throw new Error(
|
||||
`The '${tag}' doesn't satisfy semantic versioning specification`
|
||||
);
|
||||
}
|
||||
|
||||
if (!isStableSemverVersion(semverVersion)) {
|
||||
throw new Error(
|
||||
'It is not allowed to specify pre-release version to update the major tag'
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user