mirror of
https://github.com/actions/publish-action.git
synced 2025-02-24 16:22:31 +00:00
Add and configure ESLint and update configuration for Prettier (#26)
* Add ESLint and Prettier * Rebuild action * Update package.json * Update licenses * Fix review points
This commit is contained in:
parent
87579b14ff
commit
9169aa7609
6
.eslintignore
Normal file
6
.eslintignore
Normal file
@ -0,0 +1,6 @@
|
||||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!src/
|
49
.eslintrc.js
Normal file
49
.eslintrc.js
Normal file
@ -0,0 +1,49 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:eslint-plugin-jest/recommended',
|
||||
'eslint-config-prettier'
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'eslint-plugin-jest'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
'error',
|
||||
{
|
||||
'ts-ignore': 'allow-with-description'
|
||||
}
|
||||
],
|
||||
'no-console': 'error',
|
||||
'yoda': 'error',
|
||||
'prefer-const': [
|
||||
'error',
|
||||
{
|
||||
destructuring: 'all'
|
||||
}
|
||||
],
|
||||
'no-control-regex': 'off',
|
||||
'no-constant-condition': ['error', {checkLoops: false}]
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*{test,spec}.ts'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'jest/no-standalone-expect': 'off',
|
||||
'jest/no-conditional-expect': 'off',
|
||||
'no-console': 'off',
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
env: {
|
||||
node: true,
|
||||
es6: true,
|
||||
'jest/globals': true
|
||||
}
|
||||
};
|
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
* text=auto eol=lf
|
||||
.licenses/** -diff linguist-generated=true
|
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@ -2,9 +2,9 @@ name: CodeQL analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '0 3 * * 0'
|
||||
|
||||
|
14
.github/workflows/release-new-action-version.yml
vendored
14
.github/workflows/release-new-action-version.yml
vendored
@ -25,11 +25,11 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-tag
|
||||
uses: ./
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-tag
|
||||
uses: ./
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
|
BIN
.licenses/npm/semver.dep.yml
generated
BIN
.licenses/npm/semver.dep.yml
generated
Binary file not shown.
7
.prettierignore
Normal file
7
.prettierignore
Normal file
@ -0,0 +1,7 @@
|
||||
# Ignore list
|
||||
/*
|
||||
|
||||
# Do not ignore these folders:
|
||||
!__tests__/
|
||||
!.github/
|
||||
!src/
|
10
.prettierrc.js
Normal file
10
.prettierrc.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
printWidth: 80,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'none',
|
||||
bracketSpacing: false,
|
||||
arrowParens: 'avoid'
|
||||
};
|
@ -1,39 +1,43 @@
|
||||
import * as github from "@actions/github";
|
||||
import * as apiUtils from "../src/api-utils";
|
||||
import * as github from '@actions/github';
|
||||
import * as apiUtils from '../src/api-utils';
|
||||
|
||||
const prereleaseData = require("./data/pre-release.json");
|
||||
const releaseData = require("./data/release.json");
|
||||
import prereleaseData from './data/pre-release.json';
|
||||
import releaseData from './data/release.json';
|
||||
|
||||
const token = "faketoken";
|
||||
const token = 'faketoken';
|
||||
const octokitClient = github.getOctokit(token);
|
||||
|
||||
let getReleaseSpy: jest.SpyInstance;
|
||||
|
||||
process.env.GITHUB_REPOSITORY = "test/repository";
|
||||
process.env.GITHUB_REPOSITORY = 'test/repository';
|
||||
|
||||
describe("validateIfReleaseIsPublished", () => {
|
||||
beforeEach(() => {
|
||||
getReleaseSpy = jest.spyOn(octokitClient.repos, "getReleaseByTag");
|
||||
});
|
||||
describe('validateIfReleaseIsPublished', () => {
|
||||
beforeEach(() => {
|
||||
getReleaseSpy = jest.spyOn(octokitClient.repos, 'getReleaseByTag');
|
||||
});
|
||||
|
||||
it("throw if release is marked as pre-release", async () => {
|
||||
getReleaseSpy.mockReturnValue(prereleaseData);
|
||||
it('throw if release is marked as pre-release', async () => {
|
||||
getReleaseSpy.mockReturnValue(prereleaseData);
|
||||
|
||||
expect.assertions(1);
|
||||
await expect(apiUtils.validateIfReleaseIsPublished("v1.0.0", octokitClient)).rejects.toThrowError(
|
||||
"The 'v1.0.0' release is marked as pre-release. Updating tags for pre-release is not supported"
|
||||
);
|
||||
});
|
||||
expect.assertions(1);
|
||||
await expect(
|
||||
apiUtils.validateIfReleaseIsPublished('v1.0.0', octokitClient)
|
||||
).rejects.toThrow(
|
||||
"The 'v1.0.0' release is marked as pre-release. Updating tags for pre-release is not supported"
|
||||
);
|
||||
});
|
||||
|
||||
it("validate that release is published", async () => {
|
||||
getReleaseSpy.mockReturnValue(releaseData);
|
||||
it('validate that release is published', async () => {
|
||||
getReleaseSpy.mockReturnValue(releaseData);
|
||||
|
||||
expect.assertions(1);
|
||||
await expect(apiUtils.validateIfReleaseIsPublished("v1.1.0", octokitClient)).resolves.not.toThrow();
|
||||
});
|
||||
expect.assertions(1);
|
||||
await expect(
|
||||
apiUtils.validateIfReleaseIsPublished('v1.1.0', octokitClient)
|
||||
).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
});
|
@ -1,69 +1,93 @@
|
||||
import * as versionUtils from "../src/version-utils";
|
||||
import * as versionUtils from '../src/version-utils';
|
||||
import stableSemver from './data/stable-semver.json';
|
||||
import stableBuildSemver from './data/stable-build-semver.json';
|
||||
import prereleaseSemver from './data/prerelease-semver.json';
|
||||
import prereleaseBuildSemver from './data/prerelease-build-semver.json';
|
||||
|
||||
describe("isStableSemverVersion", () => {
|
||||
it("validate if a version is stable", () => {
|
||||
const semverVersion = require("./data/stable-semver.json");
|
||||
expect(versionUtils.isStableSemverVersion(semverVersion)).toBeTruthy();
|
||||
});
|
||||
describe('isStableSemverVersion', () => {
|
||||
it('validate if a version is stable', () => {
|
||||
expect(
|
||||
versionUtils.isStableSemverVersion(stableSemver as any)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("validate if a version with build metadata is stable", () => {
|
||||
const semverVersion = require("./data/stable-build-semver.json");
|
||||
expect(versionUtils.isStableSemverVersion(semverVersion)).toBeTruthy();
|
||||
});
|
||||
it('validate if a version with build metadata is stable', () => {
|
||||
expect(
|
||||
versionUtils.isStableSemverVersion(stableBuildSemver as any)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("validate if a pre-release version is not stable", () => {
|
||||
const semverVersion = require("./data/prerelease-semver.json");
|
||||
expect(versionUtils.isStableSemverVersion(semverVersion)).toBeFalsy();
|
||||
});
|
||||
it('validate if a pre-release version is not stable', () => {
|
||||
expect(
|
||||
versionUtils.isStableSemverVersion(prereleaseSemver as any)
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it("validate if a pre-release version with build metadata is not stable", () => {
|
||||
const semverVersion = require("./data/prerelease-build-semver.json");
|
||||
expect(versionUtils.isStableSemverVersion(semverVersion)).toBeFalsy();
|
||||
});
|
||||
it('validate if a pre-release version with build metadata is not stable', () => {
|
||||
expect(
|
||||
versionUtils.isStableSemverVersion(prereleaseBuildSemver as any)
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("validateSemverVersionFromTag", () => {
|
||||
it("validate a tag containing an valid semantic version", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("1.0.0")).not.toThrow();
|
||||
});
|
||||
describe('validateSemverVersionFromTag', () => {
|
||||
it('validate a tag containing a valid semantic version', () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('1.0.0')
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("validate a tag containing an valid semantic version with 'v' prefix", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("v1.0.0")).not.toThrow();
|
||||
});
|
||||
it("validate a tag containing a valid semantic version with 'v' prefix", () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('v1.0.0')
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("validate a tag containing an valid semantic version with build metadata", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("v1.0.0+20130313144700")).not.toThrow();
|
||||
});
|
||||
it('validate a tag containing a valid semantic version with build metadata', () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('v1.0.0+20130313144700')
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
it("throw when a tag contains an invalid semantic version", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("1.0.0invalid")).toThrowError(
|
||||
"The '1.0.0invalid' doesn't satisfy semantic versioning specification"
|
||||
);
|
||||
});
|
||||
it('throw when a tag contains an invalid semantic version', () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('1.0.0invalid')
|
||||
).toThrow(
|
||||
"The '1.0.0invalid' doesn't satisfy semantic versioning specification"
|
||||
);
|
||||
});
|
||||
|
||||
it("throw when a tag contains an valid unstable semantic version", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("v1.0.0-beta.1")).toThrowError(
|
||||
"It is not allowed to specify pre-release version to update the major tag"
|
||||
);
|
||||
});
|
||||
it('throw when a tag contains a valid unstable semantic version', () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('v1.0.0-beta.1')
|
||||
).toThrow(
|
||||
'It is not allowed to specify pre-release version to update the major tag'
|
||||
);
|
||||
});
|
||||
|
||||
it("throw when a tag contains an valid unstable semantic version with build metadata", () => {
|
||||
expect(() => versionUtils.validateSemverVersionFromTag("v1.0.0-beta.1+20130313144700")).toThrowError(
|
||||
"It is not allowed to specify pre-release version to update the major tag"
|
||||
);
|
||||
});
|
||||
it('throw when a tag contains a valid unstable semantic version with build metadata', () => {
|
||||
expect(() =>
|
||||
versionUtils.validateSemverVersionFromTag('v1.0.0-beta.1+20130313144700')
|
||||
).toThrow(
|
||||
'It is not allowed to specify pre-release version to update the major tag'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getMajorTagFromFullTag", () => {
|
||||
describe("get a valid major tag from full tag", () => {
|
||||
it.each([
|
||||
["1.0.0", "1"],
|
||||
["v1.0.0", "v1"],
|
||||
["v1.0.0-beta.1", "v1"],
|
||||
["v1.0.0+20130313144700", "v1"],
|
||||
] as [string, string][])("%s -> %s", (sourceTag: string, expectedMajorTag: string) => {
|
||||
const resultantMajorTag = versionUtils.getMajorTagFromFullTag(sourceTag);
|
||||
expect(resultantMajorTag).toBe(expectedMajorTag);
|
||||
});
|
||||
});
|
||||
describe('getMajorTagFromFullTag', () => {
|
||||
describe('get a valid major tag from full tag', () => {
|
||||
it.each([
|
||||
['1.0.0', '1'],
|
||||
['v1.0.0', 'v1'],
|
||||
['v1.0.0-beta.1', 'v1'],
|
||||
['v1.0.0+20130313144700', 'v1']
|
||||
] as [string, string][])(
|
||||
'%s -> %s',
|
||||
(sourceTag: string, expectedMajorTag: string) => {
|
||||
const resultantMajorTag =
|
||||
versionUtils.getMajorTagFromFullTag(sourceTag);
|
||||
expect(resultantMajorTag).toBe(expectedMajorTag);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
25
dist/index.js
vendored
25
dist/index.js
vendored
@ -58,7 +58,7 @@ async function validateIfReleaseIsPublished(tag, octokitClient) {
|
||||
try {
|
||||
const { data: foundRelease } = await octokitClient.repos.getReleaseByTag({
|
||||
...github_1.context.repo,
|
||||
tag,
|
||||
tag
|
||||
});
|
||||
if (foundRelease.prerelease) {
|
||||
throw new Error(`The '${foundRelease.name}' release is marked as pre-release. Updating tags for pre-release is not supported`);
|
||||
@ -157,7 +157,6 @@ async function run() {
|
||||
await reportStatusToSlack(slackMessage);
|
||||
}
|
||||
}
|
||||
;
|
||||
async function reportStatusToSlack(message) {
|
||||
const slackWebhook = core.getInput('slack-webhook');
|
||||
if (slackWebhook) {
|
||||
@ -9593,7 +9592,7 @@ class SemVer {
|
||||
if (identifier) {
|
||||
// 1.2.0-beta.1 bumps to 1.2.0-beta.2,
|
||||
// 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0
|
||||
if (this.prerelease[0] === identifier) {
|
||||
if (compareIdentifiers(this.prerelease[0], identifier) === 0) {
|
||||
if (isNaN(this.prerelease[1])) {
|
||||
this.prerelease = [identifier, 0]
|
||||
}
|
||||
@ -9620,7 +9619,7 @@ module.exports = SemVer
|
||||
/***/ 5925:
|
||||
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
||||
|
||||
const {MAX_LENGTH} = __nccwpck_require__(2293)
|
||||
const { MAX_LENGTH } = __nccwpck_require__(2293)
|
||||
const { re, t } = __nccwpck_require__(9523)
|
||||
const SemVer = __nccwpck_require__(8088)
|
||||
|
||||
@ -9666,7 +9665,7 @@ const SEMVER_SPEC_VERSION = '2.0.0'
|
||||
|
||||
const MAX_LENGTH = 256
|
||||
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER ||
|
||||
/* istanbul ignore next */ 9007199254740991
|
||||
/* istanbul ignore next */ 9007199254740991
|
||||
|
||||
// Max safe segment length for coercion.
|
||||
const MAX_SAFE_COMPONENT_LENGTH = 16
|
||||
@ -9675,7 +9674,7 @@ module.exports = {
|
||||
SEMVER_SPEC_VERSION,
|
||||
MAX_LENGTH,
|
||||
MAX_SAFE_INTEGER,
|
||||
MAX_SAFE_COMPONENT_LENGTH
|
||||
MAX_SAFE_COMPONENT_LENGTH,
|
||||
}
|
||||
|
||||
|
||||
@ -9721,7 +9720,7 @@ const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a)
|
||||
|
||||
module.exports = {
|
||||
compareIdentifiers,
|
||||
rcompareIdentifiers
|
||||
rcompareIdentifiers,
|
||||
}
|
||||
|
||||
|
||||
@ -9736,9 +9735,9 @@ const opts = ['includePrerelease', 'loose', 'rtl']
|
||||
const parseOptions = options =>
|
||||
!options ? {}
|
||||
: typeof options !== 'object' ? { loose: true }
|
||||
: opts.filter(k => options[k]).reduce((options, k) => {
|
||||
options[k] = true
|
||||
return options
|
||||
: opts.filter(k => options[k]).reduce((o, k) => {
|
||||
o[k] = true
|
||||
return o
|
||||
}, {})
|
||||
module.exports = parseOptions
|
||||
|
||||
@ -9760,7 +9759,7 @@ let R = 0
|
||||
|
||||
const createToken = (name, value, isGlobal) => {
|
||||
const index = R++
|
||||
debug(index, value)
|
||||
debug(name, index, value)
|
||||
t[name] = index
|
||||
src[index] = value
|
||||
re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
|
||||
@ -9928,8 +9927,8 @@ createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` +
|
||||
// Star ranges basically just allow anything at all.
|
||||
createToken('STAR', '(<|>)?=?\\s*\\*')
|
||||
// >=0.0.0 is like a star
|
||||
createToken('GTE0', '^\\s*>=\\s*0\.0\.0\\s*$')
|
||||
createToken('GTE0PRE', '^\\s*>=\\s*0\.0\.0-0\\s*$')
|
||||
createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$')
|
||||
createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$')
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
1979
package-lock.json
generated
1979
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -6,8 +6,10 @@
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build",
|
||||
"test": "jest",
|
||||
"format-check": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
|
||||
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\""
|
||||
"format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write **/*.{ts,yml,yaml}",
|
||||
"format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check **/*.{ts,yml,yaml}",
|
||||
"lint": "eslint --config ./.eslintrc.js **/*.ts",
|
||||
"lint:fix": "eslint --config ./.eslintrc.js **/*.ts --fix"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -25,16 +27,22 @@
|
||||
"homepage": "https://github.com/actions/publish-action#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.7",
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@actions/http-client": "^1.0.11",
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/semver": "^7.3.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||
"@typescript-eslint/parser": "^5.54.0",
|
||||
"@vercel/ncc": "^0.28.5",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"jest": "^27.2.5",
|
||||
"jest-circus": "^27.2.5",
|
||||
"prettier": "^2.8.4",
|
||||
"ts-jest": "^27.0.5",
|
||||
"typescript": "^4.2.4"
|
||||
}
|
||||
|
167
src/api-utils.ts
167
src/api-utils.ts
@ -1,114 +1,115 @@
|
||||
import * as core from '@actions/core';
|
||||
import { context } from '@actions/github';
|
||||
import { GitHub } from '@actions/github/lib/utils';
|
||||
import { HttpClient } from '@actions/http-client';
|
||||
import {context} from '@actions/github';
|
||||
import {GitHub} from '@actions/github/lib/utils';
|
||||
import {HttpClient} from '@actions/http-client';
|
||||
|
||||
interface GitRef {
|
||||
ref: string;
|
||||
node_id: string;
|
||||
ref: string;
|
||||
node_id: string;
|
||||
url: string;
|
||||
object: {
|
||||
type: string;
|
||||
sha: string;
|
||||
url: string;
|
||||
object: {
|
||||
type: string;
|
||||
sha: string;
|
||||
url: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
async function findTag(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<GitRef | null> {
|
||||
try {
|
||||
const { data: foundTag } = await octokitClient.git.getRef({
|
||||
...context.repo,
|
||||
ref: `tags/${tag}`
|
||||
});
|
||||
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 new Error(
|
||||
`Retrieving refs failed with the following error: ${err}`
|
||||
);
|
||||
}
|
||||
return foundTag;
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
return null;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Retrieving refs failed with the following error: ${err}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getTagSHA(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
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`
|
||||
);
|
||||
}
|
||||
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;
|
||||
return foundTag.object.sha;
|
||||
}
|
||||
|
||||
export async function validateIfReleaseIsPublished(
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
tag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { data: foundRelease } = await octokitClient.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag,
|
||||
});
|
||||
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 new Error(
|
||||
`Retrieving releases failed with the following error: ${err}`
|
||||
);
|
||||
}
|
||||
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 new Error(
|
||||
`Retrieving releases failed with the following error: ${err}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateTag(
|
||||
sourceTag: string,
|
||||
targetTag: string,
|
||||
octokitClient: InstanceType<typeof GitHub>
|
||||
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}`;
|
||||
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`);
|
||||
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.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
|
||||
});
|
||||
}
|
||||
await octokitClient.git.createRef({
|
||||
...context.repo,
|
||||
ref: `refs/${refName}`,
|
||||
sha: sourceTagSHA
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function postMessageToSlack(slackWebhook: string, message: string): Promise<void> {
|
||||
const jsonData = {text: message}
|
||||
const http = new HttpClient();
|
||||
await http.postJson(slackWebhook, jsonData);
|
||||
export async function postMessageToSlack(
|
||||
slackWebhook: string,
|
||||
message: string
|
||||
): Promise<void> {
|
||||
const jsonData = {text: message};
|
||||
const http = new HttpClient();
|
||||
await http.postJson(slackWebhook, jsonData);
|
||||
}
|
59
src/main.ts
59
src/main.ts
@ -1,40 +1,49 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import { context } from '@actions/github';
|
||||
import { updateTag, validateIfReleaseIsPublished, postMessageToSlack } from './api-utils';
|
||||
import { validateSemverVersionFromTag, getMajorTagFromFullTag } from './version-utils';
|
||||
import {context} from '@actions/github';
|
||||
import {
|
||||
updateTag,
|
||||
validateIfReleaseIsPublished,
|
||||
postMessageToSlack
|
||||
} 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');
|
||||
try {
|
||||
const token = core.getInput('token');
|
||||
const octokitClient = github.getOctokit(token);
|
||||
const sourceTagName = core.getInput('source-tag');
|
||||
|
||||
validateSemverVersionFromTag(sourceTagName);
|
||||
validateSemverVersionFromTag(sourceTagName);
|
||||
|
||||
await validateIfReleaseIsPublished(sourceTagName, octokitClient);
|
||||
await validateIfReleaseIsPublished(sourceTagName, octokitClient);
|
||||
|
||||
const majorTag = getMajorTagFromFullTag(sourceTagName);
|
||||
await updateTag(sourceTagName, majorTag, 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`);
|
||||
core.setOutput('major-tag', majorTag);
|
||||
core.info(
|
||||
`The '${majorTag}' major tag now points to the '${sourceTagName}' tag`
|
||||
);
|
||||
|
||||
const slackMessage = `The ${majorTag} tag has been successfully updated for the ${context.repo.repo} action to include changes from ${sourceTagName}`;
|
||||
await reportStatusToSlack(slackMessage);
|
||||
} catch (error) {
|
||||
core.setFailed((error as Error).message);
|
||||
const slackMessage = `The ${majorTag} tag has been successfully updated for the ${context.repo.repo} action to include changes from ${sourceTagName}`;
|
||||
await reportStatusToSlack(slackMessage);
|
||||
} catch (error) {
|
||||
core.setFailed((error as Error).message);
|
||||
|
||||
const slackMessage = `Failed to update a major tag for the ${context.repo.repo} action`;
|
||||
await reportStatusToSlack(slackMessage);
|
||||
}
|
||||
};
|
||||
const slackMessage = `Failed to update a major tag for the ${context.repo.repo} action`;
|
||||
await reportStatusToSlack(slackMessage);
|
||||
}
|
||||
}
|
||||
|
||||
async function reportStatusToSlack(message: string): Promise<void> {
|
||||
const slackWebhook = core.getInput('slack-webhook');
|
||||
if (slackWebhook) {
|
||||
await postMessageToSlack(slackWebhook, message);
|
||||
}
|
||||
const slackWebhook = core.getInput('slack-webhook');
|
||||
if (slackWebhook) {
|
||||
await postMessageToSlack(slackWebhook, message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
@ -2,24 +2,24 @@ import semverParse from 'semver/functions/parse';
|
||||
import SemVer from 'semver/classes/semver';
|
||||
|
||||
export function isStableSemverVersion(version: SemVer): boolean {
|
||||
return version.prerelease.length === 0
|
||||
return version.prerelease.length === 0;
|
||||
}
|
||||
|
||||
export function getMajorTagFromFullTag(fullTag: string): string {
|
||||
return fullTag.split('.')[0];
|
||||
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`
|
||||
);
|
||||
}
|
||||
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'
|
||||
);
|
||||
}
|
||||
if (!isStableSemverVersion(semverVersion)) {
|
||||
throw new Error(
|
||||
'It is not allowed to specify pre-release version to update the major tag'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
|
Loading…
Reference in New Issue
Block a user