Compare commits

...

20 Commits

Author SHA1 Message Date
Evgenii Korolevskii
6870bfd4e8 Update CODEOWNERS 2022-12-26 09:47:41 +01:00
Ivan
91690a7e55 Merge pull request #470 from akv-platform/apply-reusable-workflows
Update action to use reusable workflows
2022-12-22 10:50:36 +02:00
Lukas Hennies
f7b1827ed3 docs: minor hint regarding glob notation (#285) 2022-12-21 15:59:36 +01:00
IvanZosimov
55e1958307 Fix review points 2022-12-20 16:53:03 +01:00
MaksimZhukov
34b1b365e1 Merge pull request #278 from jsoref/fix-at-example
Fix @ example
2022-12-20 10:25:28 +01:00
IvanZosimov
ce7f13552d Rebuild project 2022-12-19 17:18:39 +01:00
IvanZosimov
0cad484cd0 Add .prettierrc.json to configure Prettier, reformat code 2022-12-19 17:09:22 +01:00
IvanZosimov
d42abd99fe Update prettier commands 2022-12-19 16:58:25 +01:00
IvanZosimov
e63db1786a Update licenses and rebuild action 2022-12-19 16:48:00 +01:00
IvanZosimov
cdcdd9a42c Update dependency to eliminate vulnerability 2022-12-19 16:43:21 +01:00
IvanZosimov
e07202b67f Update workflows to use reusable-workflows 2022-12-19 16:40:34 +01:00
Marko Zivic
5776c3457c Merge pull request #463 from MaksimZhukov/add-issue-templates
Add issue templates and workflow files
2022-12-14 09:50:11 +01:00
MaksimZhukov
1e8fa0b154 Add issue templates and workflow files 2022-12-07 09:17:16 +01:00
dependabot[bot]
3e20f3d061 Bump typescript from 4.8.2 to 4.8.4 (#440)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.8.2 to 4.8.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.8.2...v4.8.4)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 11:43:09 -05:00
Francesco Renzi
5c7539237e Merge pull request #444 from actions/rentziass/update-actions-core
Update @actions/core to 1.10.0
2022-10-07 11:04:13 +01:00
Francesco Renzi
d8fb392051 Update @actions/core to 1.10.0 2022-10-06 11:51:14 +01:00
Patrick Ellis
a96e5aec3e Regenerate package-lock with latest node/npm (#435)
This just added a "name" field to the innermost "package" entry.
2022-09-07 11:19:54 -04:00
dependabot[bot]
9f8414f4c4 Bump typescript from 4.6.3 to 4.8.2 (#430)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.6.3 to 4.8.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.6.3...v4.8.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-07 10:41:20 -04:00
dependabot[bot]
97727458a9 Bump prettier from 2.6.2 to 2.7.1 (#402)
Bumps [prettier](https://github.com/prettier/prettier) from 2.6.2 to 2.7.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.6.2...2.7.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-07 10:36:59 -04:00
Josh Soref
c79c655b8b Fix @ example 2021-11-23 20:57:39 -05:00
24 changed files with 451 additions and 317 deletions

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,35 @@
---
name: Bug report
about: Create a bug report
title: ''
labels: bug, needs triage
assignees: ''
---
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
<!--- Before opening up a new bug report, please make sure to check for similar existing issues -->
**Description:**
A clear and concise description of what the bug is.
**Action version:**
Specify the action version
**Platform:**
- [ ] Ubuntu
- [ ] macOS
- [ ] Windows
**Runner type:**
- [ ] Hosted
- [ ] Self-hosted
**Repro steps:**
A description with steps to reproduce the issue. If your have a public example or repo to share, please provide the link.
**Expected behavior:**
A description of what you expected to happen.
**Actual behavior:**
A description of what is actually happening.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1 @@
blank_issues_enabled: false

View File

@@ -0,0 +1,18 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request, needs triage
assignees: ''
---
<!--- Please direct any generic questions related to actions to our support community forum at https://github.community/c/code-to-cloud/github-actions/41 --->
<!--- Before opening up a new feature request, please make sure to check for similar existing issues and pull requests -->
**Description:**
Describe your proposal.
**Justification:**
Justification or a use case for your proposal.
**Are you willing to submit a PR?**
<!--- We accept contributions! -->

9
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,9 @@
**Description:**
Describe your changes.
**Related issue:**
Add link to the related issue.
**Check list:**
- [ ] Mark if documentation changes are required.
- [ ] Mark if tests were added or updated to cover the changes.

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@v2
- name: Setup node 16
uses: actions/setup-node@v2
with:
node-version: 16.x
- run: npm install
- run: npm run build
- run: npm test

17
.github/workflows/check-dist.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Check dist/
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:
jobs:
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

@@ -0,0 +1,28 @@
name: Release new action version
on:
release:
types: [released]
workflow_dispatch:
inputs:
TAG_NAME:
description: 'Tag name that the major tag will point to'
required: true
env:
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
permissions:
contents: write
jobs:
update_tag:
name: Update the major tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
environment:
name: releaseNewActionVersion
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
uses: actions/publish-action@v0.2.1
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}

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: "@actions/core" name: "@actions/core"
version: 1.9.1 version: 1.10.0
type: npm type: npm
summary: Actions core lib summary: Actions core lib
homepage: https://github.com/actions/toolkit/tree/main/packages/core homepage: https://github.com/actions/toolkit/tree/main/packages/core

View File

@@ -1,6 +1,6 @@
--- ---
name: minimatch name: minimatch
version: 3.0.4 version: 3.1.2
type: npm type: npm
summary: a glob matcher in javascript summary: a glob matcher in javascript
homepage: 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 +1 @@
* @actions/actions-runtime * @actions/setup-actions-team

View File

@@ -56,6 +56,11 @@ label1:
# Add 'label2' to any file changes within 'example2' folder # Add 'label2' to any file changes within 'example2' folder
label2: example2/* label2: example2/*
# Add label3 to any change to .txt files within the entire repository. Quotation marks are required for the leading asterisk
label3:
- '**/*.txt'
``` ```
#### Common Examples #### Common Examples
@@ -66,7 +71,7 @@ repo:
- '*' - '*'
# Add '@domain/core' label to any change within the 'core' package # Add '@domain/core' label to any change within the 'core' package
@domain/core: '@domain/core':
- package/core/* - package/core/*
- package/core/**/* - package/core/**/*

View File

@@ -1,34 +1,34 @@
export const context = { export const context = {
payload: { payload: {
pull_request: { pull_request: {
number: 123, number: 123
}, }
}, },
repo: { repo: {
owner: "monalisa", owner: 'monalisa',
repo: "helloworld", repo: 'helloworld'
}, }
}; };
const mockApi = { const mockApi = {
rest: { rest: {
issues: { issues: {
addLabels: jest.fn(), addLabels: jest.fn(),
removeLabel: jest.fn(), removeLabel: jest.fn()
}, },
pulls: { pulls: {
get: jest.fn().mockResolvedValue({}), get: jest.fn().mockResolvedValue({}),
listFiles: { listFiles: {
endpoint: { endpoint: {
merge: jest.fn().mockReturnValue({}), merge: jest.fn().mockReturnValue({})
}, }
}, }
}, },
repos: { repos: {
getContent: jest.fn(), getContent: jest.fn()
}, }
}, },
paginate: jest.fn(), paginate: jest.fn()
}; };
export const getOctokit = jest.fn().mockImplementation(() => mockApi); 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(() => { beforeAll(() => {
jest.spyOn(core, "getInput").mockImplementation((name, options) => { jest.spyOn(core, 'getInput').mockImplementation((name, options) => {
return jest.requireActual("@actions/core").getInput(name, options); return jest.requireActual('@actions/core').getInput(name, options);
}); });
}); });
const matchConfig = [{ any: ["*.txt"] }]; const matchConfig = [{any: ['*.txt']}];
describe("checkGlobs", () => { describe('checkGlobs', () => {
it("returns true when our pattern does match changed files", () => { it('returns true when our pattern does match changed files', () => {
const changedFiles = ["foo.txt", "bar.txt"]; const changedFiles = ['foo.txt', 'bar.txt'];
const result = checkGlobs(changedFiles, matchConfig); const result = checkGlobs(changedFiles, matchConfig);
expect(result).toBeTruthy(); expect(result).toBeTruthy();
}); });
it("returns false when our pattern does not match changed files", () => { it('returns false when our pattern does not match changed files', () => {
const changedFiles = ["foo.docx"]; const changedFiles = ['foo.docx'];
const result = checkGlobs(changedFiles, matchConfig); const result = checkGlobs(changedFiles, matchConfig);
expect(result).toBeFalsy(); expect(result).toBeFalsy();

View File

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

257
dist/index.js vendored
View File

@@ -47,19 +47,19 @@ const minimatch_1 = __nccwpck_require__(3973);
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { try {
const token = core.getInput("repo-token", { required: true }); const token = core.getInput('repo-token', { required: true });
const configPath = core.getInput("configuration-path", { required: true }); const configPath = core.getInput('configuration-path', { required: true });
const syncLabels = !!core.getInput("sync-labels", { required: false }); const syncLabels = !!core.getInput('sync-labels', { required: false });
const prNumber = getPrNumber(); const prNumber = getPrNumber();
if (!prNumber) { 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; return;
} }
const client = github.getOctokit(token); const client = github.getOctokit(token);
const { data: pullRequest } = yield client.rest.pulls.get({ const { data: pullRequest } = yield client.rest.pulls.get({
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
pull_number: prNumber, pull_number: prNumber
}); });
core.debug(`fetching changed files for pr #${prNumber}`); core.debug(`fetching changed files for pr #${prNumber}`);
const changedFiles = yield getChangedFiles(client, prNumber); const changedFiles = yield getChangedFiles(client, prNumber);
@@ -71,7 +71,7 @@ function run() {
if (checkGlobs(changedFiles, globs)) { if (checkGlobs(changedFiles, globs)) {
labels.push(label); labels.push(label);
} }
else if (pullRequest.labels.find((l) => l.name === label)) { else if (pullRequest.labels.find(l => l.name === label)) {
labelsToRemove.push(label); labelsToRemove.push(label);
} }
} }
@@ -101,13 +101,13 @@ function getChangedFiles(client, prNumber) {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({ const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
pull_number: prNumber, pull_number: prNumber
}); });
const listFilesResponse = yield client.paginate(listFilesOptions); const listFilesResponse = yield client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f) => f.filename); const changedFiles = listFilesResponse.map((f) => f.filename);
core.debug("found changed files:"); core.debug('found changed files:');
for (const file of changedFiles) { for (const file of changedFiles) {
core.debug(" " + file); core.debug(' ' + file);
} }
return changedFiles; return changedFiles;
}); });
@@ -127,7 +127,7 @@ function fetchContent(client, repoPath) {
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
path: repoPath, path: repoPath,
ref: github.context.sha, ref: github.context.sha
}); });
return Buffer.from(response.data.content, response.data.encoding).toString(); return Buffer.from(response.data.content, response.data.encoding).toString();
}); });
@@ -135,7 +135,7 @@ function fetchContent(client, repoPath) {
function getLabelGlobMapFromObject(configObject) { function getLabelGlobMapFromObject(configObject) {
const labelGlobs = new Map(); const labelGlobs = new Map();
for (const label in configObject) { for (const label in configObject) {
if (typeof configObject[label] === "string") { if (typeof configObject[label] === 'string') {
labelGlobs.set(label, [configObject[label]]); labelGlobs.set(label, [configObject[label]]);
} }
else if (configObject[label] instanceof Array) { else if (configObject[label] instanceof Array) {
@@ -148,15 +148,15 @@ function getLabelGlobMapFromObject(configObject) {
return labelGlobs; return labelGlobs;
} }
function toMatchConfig(config) { function toMatchConfig(config) {
if (typeof config === "string") { if (typeof config === 'string') {
return { return {
any: [config], any: [config]
}; };
} }
return config; return config;
} }
function printPattern(matcher) { function printPattern(matcher) {
return (matcher.negate ? "!" : "") + matcher.pattern; return (matcher.negate ? '!' : '') + matcher.pattern;
} }
function checkGlobs(changedFiles, globs) { function checkGlobs(changedFiles, globs) {
for (const glob of globs) { for (const glob of globs) {
@@ -183,7 +183,7 @@ function isMatch(changedFile, matchers) {
} }
// equivalent to "Array.some()" but expanded for debugging and clarity // equivalent to "Array.some()" but expanded for debugging and clarity
function checkAny(changedFiles, globs) { 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`); core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) { for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) { if (isMatch(changedFile, matchers)) {
@@ -196,7 +196,7 @@ function checkAny(changedFiles, globs) {
} }
// equivalent to "Array.every()" but expanded for debugging and clarity // equivalent to "Array.every()" but expanded for debugging and clarity
function checkAll(changedFiles, globs) { 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`); core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) { for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) { if (!isMatch(changedFile, matchers)) {
@@ -226,17 +226,17 @@ function addLabels(client, prNumber, labels) {
owner: github.context.repo.owner, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
issue_number: prNumber, issue_number: prNumber,
labels: labels, labels: labels
}); });
}); });
} }
function removeLabels(client, prNumber, labels) { function removeLabels(client, prNumber, labels) {
return __awaiter(this, void 0, void 0, function* () { 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, owner: github.context.repo.owner,
repo: github.context.repo.repo, repo: github.context.repo.repo,
issue_number: prNumber, issue_number: prNumber,
name: label, name: label
}))); })));
}); });
} }
@@ -383,7 +383,6 @@ const file_command_1 = __nccwpck_require__(717);
const utils_1 = __nccwpck_require__(5278); const utils_1 = __nccwpck_require__(5278);
const os = __importStar(__nccwpck_require__(2037)); const os = __importStar(__nccwpck_require__(2037));
const path = __importStar(__nccwpck_require__(1017)); const path = __importStar(__nccwpck_require__(1017));
const uuid_1 = __nccwpck_require__(5840);
const oidc_utils_1 = __nccwpck_require__(8041); const oidc_utils_1 = __nccwpck_require__(8041);
/** /**
* The code to exit an action * The code to exit an action
@@ -413,20 +412,9 @@ function exportVariable(name, val) {
process.env[name] = convertedVal; process.env[name] = convertedVal;
const filePath = process.env['GITHUB_ENV'] || ''; const filePath = process.env['GITHUB_ENV'] || '';
if (filePath) { if (filePath) {
const delimiter = `ghadelimiter_${uuid_1.v4()}`; return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val));
// These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter.
if (name.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
}
if (convertedVal.includes(delimiter)) {
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
}
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
file_command_1.issueCommand('ENV', commandValue);
}
else {
command_1.issueCommand('set-env', { name }, convertedVal);
} }
command_1.issueCommand('set-env', { name }, convertedVal);
} }
exports.exportVariable = exportVariable; exports.exportVariable = exportVariable;
/** /**
@@ -444,7 +432,7 @@ exports.setSecret = setSecret;
function addPath(inputPath) { function addPath(inputPath) {
const filePath = process.env['GITHUB_PATH'] || ''; const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) { if (filePath) {
file_command_1.issueCommand('PATH', inputPath); file_command_1.issueFileCommand('PATH', inputPath);
} }
else { else {
command_1.issueCommand('add-path', {}, inputPath); command_1.issueCommand('add-path', {}, inputPath);
@@ -484,7 +472,10 @@ function getMultilineInput(name, options) {
const inputs = getInput(name, options) const inputs = getInput(name, options)
.split('\n') .split('\n')
.filter(x => x !== ''); .filter(x => x !== '');
return inputs; if (options && options.trimWhitespace === false) {
return inputs;
}
return inputs.map(input => input.trim());
} }
exports.getMultilineInput = getMultilineInput; exports.getMultilineInput = getMultilineInput;
/** /**
@@ -517,8 +508,12 @@ exports.getBooleanInput = getBooleanInput;
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
function setOutput(name, value) { function setOutput(name, value) {
const filePath = process.env['GITHUB_OUTPUT'] || '';
if (filePath) {
return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value));
}
process.stdout.write(os.EOL); process.stdout.write(os.EOL);
command_1.issueCommand('set-output', { name }, value); command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value));
} }
exports.setOutput = setOutput; exports.setOutput = setOutput;
/** /**
@@ -647,7 +642,11 @@ exports.group = group;
*/ */
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
function saveState(name, value) { function saveState(name, value) {
command_1.issueCommand('save-state', { name }, value); const filePath = process.env['GITHUB_STATE'] || '';
if (filePath) {
return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value));
}
command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value));
} }
exports.saveState = saveState; exports.saveState = saveState;
/** /**
@@ -713,13 +712,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.issueCommand = void 0; exports.prepareKeyValueMessage = exports.issueFileCommand = void 0;
// We use any as a valid input type // We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(__nccwpck_require__(7147)); const fs = __importStar(__nccwpck_require__(7147));
const os = __importStar(__nccwpck_require__(2037)); const os = __importStar(__nccwpck_require__(2037));
const uuid_1 = __nccwpck_require__(5840);
const utils_1 = __nccwpck_require__(5278); const utils_1 = __nccwpck_require__(5278);
function issueCommand(command, message) { function issueFileCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`]; const filePath = process.env[`GITHUB_${command}`];
if (!filePath) { if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`); throw new Error(`Unable to find environment variable for file command ${command}`);
@@ -731,7 +731,22 @@ function issueCommand(command, message) {
encoding: 'utf8' encoding: 'utf8'
}); });
} }
exports.issueCommand = issueCommand; exports.issueFileCommand = issueFileCommand;
function prepareKeyValueMessage(key, value) {
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
const convertedValue = utils_1.toCommandValue(value);
// These should realistically never happen, but just in case someone finds a
// way to exploit uuid generation let's not allow keys or values that contain
// the delimiter.
if (key.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
}
if (convertedValue.includes(delimiter)) {
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
}
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;
}
exports.prepareKeyValueMessage = prepareKeyValueMessage;
//# sourceMappingURL=file-command.js.map //# sourceMappingURL=file-command.js.map
/***/ }), /***/ }),
@@ -9995,10 +10010,10 @@ module.exports = new Type('tag:yaml.org,2002:timestamp', {
module.exports = minimatch module.exports = minimatch
minimatch.Minimatch = Minimatch minimatch.Minimatch = Minimatch
var path = { sep: '/' } var path = (function () { try { return __nccwpck_require__(1017) } catch (e) {}}()) || {
try { sep: '/'
path = __nccwpck_require__(1017) }
} catch (er) {} minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = __nccwpck_require__(3717) var expand = __nccwpck_require__(3717)
@@ -10050,43 +10065,64 @@ function filter (pattern, options) {
} }
function ext (a, b) { function ext (a, b) {
a = a || {}
b = b || {} b = b || {}
var t = {} var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) { Object.keys(a).forEach(function (k) {
t[k] = a[k] t[k] = a[k]
}) })
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t return t
} }
minimatch.defaults = function (def) { 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 orig = minimatch
var m = function minimatch (p, pattern, options) { 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) { m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, 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 return m
} }
Minimatch.defaults = function (def) { Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch return minimatch.defaults(def).Minimatch
} }
function minimatch (p, pattern, options) { function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
@@ -10095,9 +10131,6 @@ function minimatch (p, pattern, options) {
return false return false
} }
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p) return new Minimatch(pattern, options).match(p)
} }
@@ -10106,15 +10139,14 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options) return new Minimatch(pattern, options)
} }
if (typeof pattern !== 'string') { assertValidPattern(pattern)
throw new TypeError('glob pattern string required')
}
if (!options) options = {} if (!options) options = {}
pattern = pattern.trim() pattern = pattern.trim()
// windows support: need to use /, not \ // windows support: need to use /, not \
if (path.sep !== '/') { if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/') pattern = pattern.split(path.sep).join('/')
} }
@@ -10125,6 +10157,7 @@ function Minimatch (pattern, options) {
this.negate = false this.negate = false
this.comment = false this.comment = false
this.empty = false this.empty = false
this.partial = !!options.partial
// make the set of regexps etc. // make the set of regexps etc.
this.make() this.make()
@@ -10134,9 +10167,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make Minimatch.prototype.make = make
function make () { function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern var pattern = this.pattern
var options = this.options var options = this.options
@@ -10156,7 +10186,7 @@ function make () {
// step 2: expand braces // step 2: expand braces
var set = this.globSet = this.braceExpand() 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) this.debug(this.pattern, set)
@@ -10236,12 +10266,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined' pattern = typeof pattern === 'undefined'
? this.pattern : pattern ? this.pattern : pattern
if (typeof pattern === 'undefined') { assertValidPattern(pattern)
throw new TypeError('undefined pattern')
}
if (options.nobrace || // Thanks to Yeting Li <https://github.com/yetingli> for
!pattern.match(/\{.*\}/)) { // improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand. // shortcut. no need to expand.
return [pattern] return [pattern]
} }
@@ -10249,6 +10278,17 @@ function braceExpand (pattern, options) {
return expand(pattern) 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. // parse a component of the expanded set.
// At this point, no pattern may contain "/" in it // At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full // so we're going to return a 2d array, where each entry is the full
@@ -10263,14 +10303,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse Minimatch.prototype.parse = parse
var SUBPARSE = {} var SUBPARSE = {}
function parse (pattern, isSub) { function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) { assertValidPattern(pattern)
throw new TypeError('pattern is too long')
}
var options = this.options var options = this.options
// shortcuts // shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return '' if (pattern === '') return ''
var re = '' var re = ''
@@ -10326,10 +10369,12 @@ function parse (pattern, isSub) {
} }
switch (c) { switch (c) {
case '/': /* istanbul ignore next */
case '/': {
// completely not allowed, even escaped. // completely not allowed, even escaped.
// Should already be path-split by now. // Should already be path-split by now.
return false return false
}
case '\\': case '\\':
clearStateChar() clearStateChar()
@@ -10448,25 +10493,23 @@ function parse (pattern, isSub) {
// handle the case where we left a class open. // handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]" // "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) { // split where the last [ was, make sure we don't have
// split where the last [ was, make sure we don't have // an invalid re. if so, re-walk the contents of the
// an invalid re. if so, re-walk the contents of the // would-be class to re-translate any characters that
// would-be class to re-translate any characters that // were passed through as-is
// were passed through as-is // TODO: It would probably be faster to determine this
// TODO: It would probably be faster to determine this // without a try/catch and a new RegExp, but it's tricky
// without a try/catch and a new RegExp, but it's tricky // to do safely. For now, this is safe and works.
// to do safely. For now, this is safe and works. var cs = pattern.substring(classStart + 1, i)
var cs = pattern.substring(classStart + 1, i) try {
try { RegExp('[' + cs + ']')
RegExp('[' + cs + ']') } catch (er) {
} catch (er) { // not a valid class!
// not a valid class! var sp = this.parse(cs, SUBPARSE)
var sp = this.parse(cs, SUBPARSE) re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' hasMagic = hasMagic || sp[1]
hasMagic = hasMagic || sp[1] inClass = false
inClass = false continue
continue
}
} }
// finish up the class. // finish up the class.
@@ -10550,9 +10593,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot // something that could conceivably capture a dot
var addPatternStart = false var addPatternStart = false
switch (re.charAt(0)) { switch (re.charAt(0)) {
case '.': case '[': case '.': case '(': addPatternStart = true
case '[':
case '(': addPatternStart = true
} }
// Hack to work around lack of negative lookbehind in JS // Hack to work around lack of negative lookbehind in JS
@@ -10614,7 +10655,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : '' var flags = options.nocase ? 'i' : ''
try { try {
var regExp = new RegExp('^' + re + '$', flags) 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 // If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of // anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line // the string, which is of course impossible, except in multi-line
@@ -10672,7 +10713,7 @@ function makeRe () {
try { try {
this.regexp = new RegExp(re, flags) this.regexp = new RegExp(re, flags)
} catch (ex) { } catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false this.regexp = false
} }
return this.regexp return this.regexp
@@ -10690,8 +10731,8 @@ minimatch.match = function (list, pattern, options) {
return list return list
} }
Minimatch.prototype.match = match Minimatch.prototype.match = function match (f, partial) {
function match (f, partial) { if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern) this.debug('match', f, this.pattern)
// short-circuit in the case of busted things. // short-circuit in the case of busted things.
// comments, etc. // comments, etc.
@@ -10773,6 +10814,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible. // should be impossible.
// some invalid regexp stuff in the set. // some invalid regexp stuff in the set.
/* istanbul ignore if */
if (p === false) return false if (p === false) return false
if (p === GLOBSTAR) { if (p === GLOBSTAR) {
@@ -10846,6 +10888,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// no match was found. // no match was found.
// However, in partial mode, we can't say this is necessarily over. // However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then // If there's more *pattern* left, then
/* istanbul ignore if */
if (partial) { if (partial) {
// ran out of file // ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr) this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
@@ -10859,11 +10902,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// patterns with magic have been turned into regexps. // patterns with magic have been turned into regexps.
var hit var hit
if (typeof p === 'string') { if (typeof p === 'string') {
if (options.nocase) { hit = f === p
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
this.debug('string match', p, f, hit) this.debug('string match', p, f, hit)
} else { } else {
hit = f.match(p) hit = f.match(p)
@@ -10894,16 +10933,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of // this is ok if we're doing the match as part of
// a glob fs traversal. // a glob fs traversal.
return partial return partial
} else if (pi === pl) { } else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left. // ran out of pattern, still have file left.
// this is only acceptable if we're on the very last // this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash. // empty segment of a file with a trailing slash.
// a/* should match a/b/ // a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') return (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
} }
// should be unreachable. // should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?') throw new Error('wtf?')
} }

55
package-lock.json generated
View File

@@ -5,10 +5,11 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "labeler",
"version": "4.0.1", "version": "4.0.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.9.1", "@actions/core": "^1.10.0",
"@actions/github": "^5.0.0", "@actions/github": "^5.0.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
@@ -20,15 +21,15 @@
"@types/node": "^16.11.7", "@types/node": "^16.11.7",
"@vercel/ncc": "^0.34.0", "@vercel/ncc": "^0.34.0",
"jest": "^27.5.1", "jest": "^27.5.1",
"prettier": "^2.6.2", "prettier": "^2.7.1",
"ts-jest": "^27.1.3", "ts-jest": "^27.1.3",
"typescript": "^4.6.3" "typescript": "^4.8.4"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "1.9.1", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"dependencies": { "dependencies": {
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"uuid": "^8.3.2" "uuid": "^8.3.2"
@@ -3305,9 +3306,9 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.0.4", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
}, },
@@ -3583,9 +3584,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "2.6.2", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin-prettier.js" "prettier": "bin-prettier.js"
@@ -4151,9 +4152,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.6.3", "version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -4412,9 +4413,9 @@
}, },
"dependencies": { "dependencies": {
"@actions/core": { "@actions/core": {
"version": "1.9.1", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
"requires": { "requires": {
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"uuid": "^8.3.2" "uuid": "^8.3.2"
@@ -6993,9 +6994,9 @@
"dev": true "dev": true
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@@ -7205,9 +7206,9 @@
"dev": true "dev": true
}, },
"prettier": { "prettier": {
"version": "2.6.2", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true "dev": true
}, },
"pretty-format": { "pretty-format": {
@@ -7605,9 +7606,9 @@
} }
}, },
"typescript": { "typescript": {
"version": "4.6.3", "version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"dev": true "dev": true
}, },
"universal-user-agent": { "universal-user-agent": {

View File

@@ -5,8 +5,9 @@
"main": "lib/main.js", "main": "lib/main.js",
"scripts": { "scripts": {
"build": "tsc && ncc build lib/main.js", "build": "tsc && ncc build lib/main.js",
"format": "prettier --write \"**/*.ts\"", "format": "prettier --write **/*.ts",
"format-check": "prettier --check \"**/*.ts\"", "format-check": "prettier --check **/*.ts",
"lint": "echo \"Fake command that does nothing. It is used in reusable workflows\"",
"test": "jest" "test": "jest"
}, },
"repository": { "repository": {
@@ -22,7 +23,7 @@
"author": "GitHub", "author": "GitHub",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.9.1", "@actions/core": "^1.10.0",
"@actions/github": "^5.0.0", "@actions/github": "^5.0.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"minimatch": "^3.0.4" "minimatch": "^3.0.4"
@@ -34,8 +35,8 @@
"@types/js-yaml": "^4.0.5", "@types/js-yaml": "^4.0.5",
"@vercel/ncc": "^0.34.0", "@vercel/ncc": "^0.34.0",
"jest": "^27.5.1", "jest": "^27.5.1",
"prettier": "^2.6.2", "prettier": "^2.7.1",
"ts-jest": "^27.1.3", "ts-jest": "^27.1.3",
"typescript": "^4.6.3" "typescript": "^4.8.4"
} }
} }

View File

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

View File

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