Merge pull request #470 from akv-platform/apply-reusable-workflows

Update action to use reusable workflows
This commit is contained in:
Ivan
2022-12-22 10:50:36 +02:00
committed by GitHub
17 changed files with 278 additions and 307 deletions

17
.github/workflows/basic-validation.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Basic validation
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
jobs:
call-basic-validation:
name: Basic validation
uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main

View File

@@ -1,28 +0,0 @@
name: Build & Test
on:
pull_request:
paths-ignore:
- '**.md'
push:
branches:
- main
- releases/*
paths-ignore:
- '**.md'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v3
- name: Setup node 16
uses: actions/setup-node@v3
with:
node-version: 16.x
- run: npm install
- run: npm run build
- run: npm test

View File

@@ -1,8 +1,3 @@
# `dist/index.js` is a special file in Actions.
# When you reference an action with `uses:` in a workflow,
# `index.js` is the code that will run.
# For our project, we generate this file through a build process from other source files.
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
name: Check dist/
on:
@@ -17,36 +12,6 @@ on:
workflow_dispatch:
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set Node.js 16.x
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: npm
- name: Install dependencies
run: npm ci
- name: Rebuild the dist/ directory
run: npm run build
- name: Compare the expected and actual dist/ directories
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. See status below:"
git diff
exit 1
fi
id: diff
# If index.js was different than expected, upload the expected version as an artifact
- uses: actions/upload-artifact@v3
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with:
name: dist
path: dist/
call-check-dist:
name: Check dist/
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main

14
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: CodeQL analysis
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 3 * * 0'
jobs:
call-codeQL-analysis:
name: CodeQL analysis
uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main

15
.github/workflows/licensed.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Licensed
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
jobs:
call-licensed:
name: Licensed
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main

View File

@@ -1,4 +1,5 @@
name: Release new action version
on:
release:
types: [released]

View File

@@ -1,50 +0,0 @@
name: Licenses
on:
push:
branches: [main]
paths: [package.json, package-lock.json]
pull_request:
branches: [main]
paths: [package.json, package-lock.json]
workflow_dispatch:
jobs:
# Updates our cache of license files in response to changes to our dependencies
# declared in package-lock.json. Automatically commits the changes and pushes
# them to your branch. NB `check_license_status` should always run *after* this
#
# see https://github.com/actions/labeler/pull/155 for more context
update_licenses:
runs-on: ubuntu-latest
name: Update Licenses
steps:
- uses: actions/checkout@v1
- uses: jonabc/setup-licensed@v1
with:
version: '3.x'
github_token: ${{ secrets.GITHUB_TOKEN }}
- run: npm install --production
- uses: jonabc/licensed-ci@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
# Fails if any of our dependencies have licenses that our incompatible with our
# requirements (see .licensed.yml) OR if any of our dependencies have been
# upgraded to a new version without us having updated their corresponding
# license metadata file in .licenses/
#
# see https://github.com/actions/labeler/pull/91 for more context
check_licenses:
needs: update_licenses
if: always() # always run after we update the license cache. if it failed, we will probably just fail as well
runs-on: ubuntu-latest
name: Check Licenses
steps:
- uses: actions/checkout@v2
- uses: jonabc/setup-licensed@v1.0.2
with:
version: '3.x'
github_token: ${{ secrets.GITHUB_TOKEN }}
- run: npm install
- run: licensed status

View File

@@ -1,6 +1,6 @@
---
name: minimatch
version: 3.0.4
version: 3.1.2
type: npm
summary: a glob matcher in javascript
homepage:

12
.prettierrc.json Normal file
View File

@@ -0,0 +1,12 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript",
"endOfLine": "auto"
}

View File

@@ -1,34 +1,34 @@
export const context = {
payload: {
pull_request: {
number: 123,
},
number: 123
}
},
repo: {
owner: "monalisa",
repo: "helloworld",
},
owner: 'monalisa',
repo: 'helloworld'
}
};
const mockApi = {
rest: {
issues: {
addLabels: jest.fn(),
removeLabel: jest.fn(),
removeLabel: jest.fn()
},
pulls: {
get: jest.fn().mockResolvedValue({}),
listFiles: {
endpoint: {
merge: jest.fn().mockReturnValue({}),
},
},
merge: jest.fn().mockReturnValue({})
}
}
},
repos: {
getContent: jest.fn(),
},
getContent: jest.fn()
}
},
paginate: jest.fn(),
paginate: jest.fn()
};
export const getOctokit = jest.fn().mockImplementation(() => mockApi);

View File

@@ -1,27 +1,27 @@
import { checkGlobs } from "../src/labeler";
import {checkGlobs} from '../src/labeler';
import * as core from "@actions/core";
import * as core from '@actions/core';
jest.mock("@actions/core");
jest.mock('@actions/core');
beforeAll(() => {
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
return jest.requireActual("@actions/core").getInput(name, options);
jest.spyOn(core, 'getInput').mockImplementation((name, options) => {
return jest.requireActual('@actions/core').getInput(name, options);
});
});
const matchConfig = [{ any: ["*.txt"] }];
const matchConfig = [{any: ['*.txt']}];
describe("checkGlobs", () => {
it("returns true when our pattern does match changed files", () => {
const changedFiles = ["foo.txt", "bar.txt"];
describe('checkGlobs', () => {
it('returns true when our pattern does match changed files', () => {
const changedFiles = ['foo.txt', 'bar.txt'];
const result = checkGlobs(changedFiles, matchConfig);
expect(result).toBeTruthy();
});
it("returns false when our pattern does not match changed files", () => {
const changedFiles = ["foo.docx"];
it('returns false when our pattern does not match changed files', () => {
const changedFiles = ['foo.docx'];
const result = checkGlobs(changedFiles, matchConfig);
expect(result).toBeFalsy();

View File

@@ -1,45 +1,45 @@
import { run } from "../src/labeler";
import * as github from "@actions/github";
import * as core from "@actions/core";
import {run} from '../src/labeler';
import * as github from '@actions/github';
import * as core from '@actions/core';
const fs = jest.requireActual("fs");
const fs = jest.requireActual('fs');
jest.mock("@actions/core");
jest.mock("@actions/github");
jest.mock('@actions/core');
jest.mock('@actions/github');
const gh = github.getOctokit("_");
const addLabelsMock = jest.spyOn(gh.rest.issues, "addLabels");
const removeLabelMock = jest.spyOn(gh.rest.issues, "removeLabel");
const reposMock = jest.spyOn(gh.rest.repos, "getContent");
const paginateMock = jest.spyOn(gh, "paginate");
const getPullMock = jest.spyOn(gh.rest.pulls, "get");
const gh = github.getOctokit('_');
const addLabelsMock = jest.spyOn(gh.rest.issues, 'addLabels');
const removeLabelMock = jest.spyOn(gh.rest.issues, 'removeLabel');
const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const yamlFixtures = {
"only_pdfs.yml": fs.readFileSync("__tests__/fixtures/only_pdfs.yml"),
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
};
afterAll(() => jest.restoreAllMocks());
describe("run", () => {
it("adds labels to PRs that match our glob patterns", async () => {
usingLabelerConfigYaml("only_pdfs.yml");
mockGitHubResponseChangedFiles("foo.pdf");
describe('run', () => {
it('adds labels to PRs that match our glob patterns', async () => {
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
await run();
expect(removeLabelMock).toHaveBeenCalledTimes(0);
expect(addLabelsMock).toHaveBeenCalledTimes(1);
expect(addLabelsMock).toHaveBeenCalledWith({
owner: "monalisa",
repo: "helloworld",
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ["touched-a-pdf-file"],
labels: ['touched-a-pdf-file']
});
});
it("does not add labels to PRs that do not match our glob patterns", async () => {
usingLabelerConfigYaml("only_pdfs.yml");
mockGitHubResponseChangedFiles("foo.txt");
it('does not add labels to PRs that do not match our glob patterns', async () => {
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
await run();
@@ -47,23 +47,23 @@ describe("run", () => {
expect(addLabelsMock).toHaveBeenCalledTimes(0);
});
it("(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern", async () => {
it('(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern', async () => {
let mockInput = {
"repo-token": "foo",
"configuration-path": "bar",
"sync-labels": true,
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': true
};
jest
.spyOn(core, "getInput")
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
usingLabelerConfigYaml("only_pdfs.yml");
mockGitHubResponseChangedFiles("foo.txt");
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{ name: "touched-a-pdf-file" }],
},
labels: [{name: 'touched-a-pdf-file'}]
}
});
await run();
@@ -71,30 +71,30 @@ describe("run", () => {
expect(addLabelsMock).toHaveBeenCalledTimes(0);
expect(removeLabelMock).toHaveBeenCalledTimes(1);
expect(removeLabelMock).toHaveBeenCalledWith({
owner: "monalisa",
repo: "helloworld",
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
name: "touched-a-pdf-file",
name: 'touched-a-pdf-file'
});
});
it("(with sync-labels: false) it issues no delete calls even when there are preexisting PR labels that no longer match the glob pattern", async () => {
it('(with sync-labels: false) it issues no delete calls even when there are preexisting PR labels that no longer match the glob pattern', async () => {
let mockInput = {
"repo-token": "foo",
"configuration-path": "bar",
"sync-labels": false,
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': false
};
jest
.spyOn(core, "getInput")
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
usingLabelerConfigYaml("only_pdfs.yml");
mockGitHubResponseChangedFiles("foo.txt");
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{ name: "touched-a-pdf-file" }],
},
labels: [{name: 'touched-a-pdf-file'}]
}
});
await run();
@@ -106,11 +106,11 @@ describe("run", () => {
function usingLabelerConfigYaml(fixtureName: keyof typeof yamlFixtures): void {
reposMock.mockResolvedValue(<any>{
data: { content: yamlFixtures[fixtureName], encoding: "utf8" },
data: {content: yamlFixtures[fixtureName], encoding: 'utf8'}
});
}
function mockGitHubResponseChangedFiles(...files: string[]): void {
const returnValue = files.map((f) => ({ filename: f }));
const returnValue = files.map(f => ({filename: f}));
paginateMock.mockReturnValue(<any>returnValue);
}

200
dist/index.js vendored
View File

@@ -47,19 +47,19 @@ const minimatch_1 = __nccwpck_require__(3973);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const token = core.getInput("repo-token", { required: true });
const configPath = core.getInput("configuration-path", { required: true });
const syncLabels = !!core.getInput("sync-labels", { required: false });
const token = core.getInput('repo-token', { required: true });
const configPath = core.getInput('configuration-path', { required: true });
const syncLabels = !!core.getInput('sync-labels', { required: false });
const prNumber = getPrNumber();
if (!prNumber) {
console.log("Could not get pull request number from context, exiting");
console.log('Could not get pull request number from context, exiting');
return;
}
const client = github.getOctokit(token);
const { data: pullRequest } = yield client.rest.pulls.get({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber,
pull_number: prNumber
});
core.debug(`fetching changed files for pr #${prNumber}`);
const changedFiles = yield getChangedFiles(client, prNumber);
@@ -71,7 +71,7 @@ function run() {
if (checkGlobs(changedFiles, globs)) {
labels.push(label);
}
else if (pullRequest.labels.find((l) => l.name === label)) {
else if (pullRequest.labels.find(l => l.name === label)) {
labelsToRemove.push(label);
}
}
@@ -101,13 +101,13 @@ function getChangedFiles(client, prNumber) {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber,
pull_number: prNumber
});
const listFilesResponse = yield client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f) => f.filename);
core.debug("found changed files:");
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(" " + file);
core.debug(' ' + file);
}
return changedFiles;
});
@@ -127,7 +127,7 @@ function fetchContent(client, repoPath) {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
path: repoPath,
ref: github.context.sha,
ref: github.context.sha
});
return Buffer.from(response.data.content, response.data.encoding).toString();
});
@@ -135,7 +135,7 @@ function fetchContent(client, repoPath) {
function getLabelGlobMapFromObject(configObject) {
const labelGlobs = new Map();
for (const label in configObject) {
if (typeof configObject[label] === "string") {
if (typeof configObject[label] === 'string') {
labelGlobs.set(label, [configObject[label]]);
}
else if (configObject[label] instanceof Array) {
@@ -148,15 +148,15 @@ function getLabelGlobMapFromObject(configObject) {
return labelGlobs;
}
function toMatchConfig(config) {
if (typeof config === "string") {
if (typeof config === 'string') {
return {
any: [config],
any: [config]
};
}
return config;
}
function printPattern(matcher) {
return (matcher.negate ? "!" : "") + matcher.pattern;
return (matcher.negate ? '!' : '') + matcher.pattern;
}
function checkGlobs(changedFiles, globs) {
for (const glob of globs) {
@@ -183,7 +183,7 @@ function isMatch(changedFile, matchers) {
}
// equivalent to "Array.some()" but expanded for debugging and clarity
function checkAny(changedFiles, globs) {
const matchers = globs.map((g) => new minimatch_1.Minimatch(g));
const matchers = globs.map(g => new minimatch_1.Minimatch(g));
core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) {
@@ -196,7 +196,7 @@ function checkAny(changedFiles, globs) {
}
// equivalent to "Array.every()" but expanded for debugging and clarity
function checkAll(changedFiles, globs) {
const matchers = globs.map((g) => new minimatch_1.Minimatch(g));
const matchers = globs.map(g => new minimatch_1.Minimatch(g));
core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) {
@@ -226,17 +226,17 @@ function addLabels(client, prNumber, labels) {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: prNumber,
labels: labels,
labels: labels
});
});
}
function removeLabels(client, prNumber, labels) {
return __awaiter(this, void 0, void 0, function* () {
yield Promise.all(labels.map((label) => client.rest.issues.removeLabel({
yield Promise.all(labels.map(label => client.rest.issues.removeLabel({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: prNumber,
name: label,
name: label
})));
});
}
@@ -10010,10 +10010,10 @@ module.exports = new Type('tag:yaml.org,2002:timestamp', {
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = __nccwpck_require__(1017)
} catch (er) {}
var path = (function () { try { return __nccwpck_require__(1017) } catch (e) {}}()) || {
sep: '/'
}
minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = __nccwpck_require__(3717)
@@ -10065,43 +10065,64 @@ function filter (pattern, options) {
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
return orig(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
@@ -10110,9 +10131,6 @@ function minimatch (p, pattern, options) {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
@@ -10121,15 +10139,14 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
@@ -10140,6 +10157,7 @@ function Minimatch (pattern, options) {
this.negate = false
this.comment = false
this.empty = false
this.partial = !!options.partial
// make the set of regexps etc.
this.make()
@@ -10149,9 +10167,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
@@ -10171,7 +10186,7 @@ function make () {
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set)
@@ -10251,12 +10266,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new TypeError('undefined pattern')
}
assertValidPattern(pattern)
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// Thanks to Yeting Li <https://github.com/yetingli> for
// improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand.
return [pattern]
}
@@ -10264,6 +10278,17 @@ function braceExpand (pattern, options) {
return expand(pattern)
}
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
@@ -10278,14 +10303,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) {
throw new TypeError('pattern is too long')
}
assertValidPattern(pattern)
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return ''
var re = ''
@@ -10341,10 +10369,12 @@ function parse (pattern, isSub) {
}
switch (c) {
case '/':
/* istanbul ignore next */
case '/': {
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
}
case '\\':
clearStateChar()
@@ -10463,25 +10493,23 @@ function parse (pattern, isSub) {
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// finish up the class.
@@ -10565,9 +10593,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
case '[': case '.': case '(': addPatternStart = true
}
// Hack to work around lack of negative lookbehind in JS
@@ -10629,7 +10655,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : ''
try {
var regExp = new RegExp('^' + re + '$', flags)
} catch (er) {
} catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line
@@ -10687,7 +10713,7 @@ function makeRe () {
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
} catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false
}
return this.regexp
@@ -10705,8 +10731,8 @@ minimatch.match = function (list, pattern, options) {
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
Minimatch.prototype.match = function match (f, partial) {
if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
@@ -10788,6 +10814,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible.
// some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false
if (p === GLOBSTAR) {
@@ -10861,6 +10888,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
@@ -10874,11 +10902,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
hit = f === p
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
@@ -10909,16 +10933,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
} else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
return (fi === fl - 1) && (file[fi] === '')
}
// should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?')
}

12
package-lock.json generated
View File

@@ -3306,9 +3306,9 @@
}
},
"node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -6994,9 +6994,9 @@
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": {
"brace-expansion": "^1.1.7"
}

View File

@@ -5,8 +5,9 @@
"main": "lib/main.js",
"scripts": {
"build": "tsc && ncc build lib/main.js",
"format": "prettier --write \"**/*.ts\"",
"format-check": "prettier --check \"**/*.ts\"",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
"test": "jest"
},
"repository": {

View File

@@ -1,7 +1,7 @@
import * as core from "@actions/core";
import * as github from "@actions/github";
import * as yaml from "js-yaml";
import { Minimatch, IMinimatch } from "minimatch";
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as yaml from 'js-yaml';
import {Minimatch, IMinimatch} from 'minimatch';
interface MatchConfig {
all?: string[];
@@ -13,22 +13,22 @@ type ClientType = ReturnType<typeof github.getOctokit>;
export async function run() {
try {
const token = core.getInput("repo-token", { required: true });
const configPath = core.getInput("configuration-path", { required: true });
const syncLabels = !!core.getInput("sync-labels", { required: false });
const token = core.getInput('repo-token', {required: true});
const configPath = core.getInput('configuration-path', {required: true});
const syncLabels = !!core.getInput('sync-labels', {required: false});
const prNumber = getPrNumber();
if (!prNumber) {
console.log("Could not get pull request number from context, exiting");
console.log('Could not get pull request number from context, exiting');
return;
}
const client: ClientType = github.getOctokit(token);
const { data: pullRequest } = await client.rest.pulls.get({
const {data: pullRequest} = await client.rest.pulls.get({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber,
pull_number: prNumber
});
core.debug(`fetching changed files for pr #${prNumber}`);
@@ -44,7 +44,7 @@ export async function run() {
core.debug(`processing ${label}`);
if (checkGlobs(changedFiles, globs)) {
labels.push(label);
} else if (pullRequest.labels.find((l) => l.name === label)) {
} else if (pullRequest.labels.find(l => l.name === label)) {
labelsToRemove.push(label);
}
}
@@ -78,15 +78,15 @@ async function getChangedFiles(
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber,
pull_number: prNumber
});
const listFilesResponse = await client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f: any) => f.filename);
core.debug("found changed files:");
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(" " + file);
core.debug(' ' + file);
}
return changedFiles;
@@ -116,7 +116,7 @@ async function fetchContent(
owner: github.context.repo.owner,
repo: github.context.repo.repo,
path: repoPath,
ref: github.context.sha,
ref: github.context.sha
});
return Buffer.from(response.data.content, response.data.encoding).toString();
@@ -127,7 +127,7 @@ function getLabelGlobMapFromObject(
): Map<string, StringOrMatchConfig[]> {
const labelGlobs: Map<string, StringOrMatchConfig[]> = new Map();
for (const label in configObject) {
if (typeof configObject[label] === "string") {
if (typeof configObject[label] === 'string') {
labelGlobs.set(label, [configObject[label]]);
} else if (configObject[label] instanceof Array) {
labelGlobs.set(label, configObject[label]);
@@ -142,9 +142,9 @@ function getLabelGlobMapFromObject(
}
function toMatchConfig(config: StringOrMatchConfig): MatchConfig {
if (typeof config === "string") {
if (typeof config === 'string') {
return {
any: [config],
any: [config]
};
}
@@ -152,7 +152,7 @@ function toMatchConfig(config: StringOrMatchConfig): MatchConfig {
}
function printPattern(matcher: IMinimatch): string {
return (matcher.negate ? "!" : "") + matcher.pattern;
return (matcher.negate ? '!' : '') + matcher.pattern;
}
export function checkGlobs(
@@ -185,7 +185,7 @@ function isMatch(changedFile: string, matchers: IMinimatch[]): boolean {
// equivalent to "Array.some()" but expanded for debugging and clarity
function checkAny(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map((g) => new Minimatch(g));
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) {
@@ -200,7 +200,7 @@ function checkAny(changedFiles: string[], globs: string[]): boolean {
// equivalent to "Array.every()" but expanded for debugging and clarity
function checkAll(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map((g) => new Minimatch(g));
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) {
@@ -238,7 +238,7 @@ async function addLabels(
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: prNumber,
labels: labels,
labels: labels
});
}
@@ -248,12 +248,12 @@ async function removeLabels(
labels: string[]
) {
await Promise.all(
labels.map((label) =>
labels.map(label =>
client.rest.issues.removeLabel({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: prNumber,
name: label,
name: label
})
)
);

View File

@@ -1,3 +1,3 @@
import { run } from "./labeler";
import {run} from './labeler';
run();