Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added output #60

Merged
merged 21 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 44 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ jobs:

Various inputs are defined in [`action.yml`](action.yml) to let you configure the labeler:

| Name | Description | Default |
| - | - | - |
| `repo-token` | Token to use to authorize label changes. Typically the `GITHUB_TOKEN` secret, with `contents:read` and `pull-requests:write` access | `github.token` |
| `configuration-path` | The path to the label configuration file | `.github/labeler.yml` |
| `sync-labels` | Whether or not to remove labels when matching files are reverted or no longer changed by the PR | `false` |
| `dot` | Whether or not to auto-include paths starting with dot (e.g. `.github`) | `false` |
| Name | Description | Default |
|----------------------|-------------------------------------------------------------------------------------------------|-----------------------|
| `repo-token` | Token to use to authorize label changes. Typically the GITHUB_TOKEN secret | N/A |
| `configuration-path` | The path to the label configuration file | `.github/labeler.yml` |
| `sync-labels` | Whether or not to remove labels when matching files are reverted or no longer changed by the PR | `false` |
| `dot` | Whether or not to auto-include paths starting with dot (e.g. `.github`) | `false` |

When `dot` is disabled and you want to include _all_ files in a folder:

Expand All @@ -131,6 +131,44 @@ label1:
- path/to/folder/**
```

#### Outputs

Labeler provides the following outputs:

| Name | Description |
|--------------|-----------------------------------------------------------|
| `new-labels` | A comma-separated list of all new labels |
| `all-labels` | A comma-separated list of all labels that the PR contains |

The following example performs steps based on the output of labeler:
```yml
name: "My workflow"
on:
- pull_request_target

jobs:
triage:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- id: label-the-PR
uses: actions/labeler@v3

- id: run-frontend-tests
if: contains(fromJson(steps.label-the-PR.outputs.all-labels), 'frontend')
run: |
echo "Running frontend tests..."
# Put your commands for running frontend tests here

- id: run-backend-tests
if: contains(fromJson(steps.label-the-PR.outputs.all-labels), 'backend')
run: |
echo "Running backend tests..."
# Put your commands for running backend tests here
```

## Permissions

In order to add labels to pull requests, the GitHub labeler action requires
Expand Down
30 changes: 30 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const coreWarningMock = jest.spyOn(core, 'warning');
const setOutputSpy = jest.spyOn(core, 'setOutput');

const yamlFixtures = {
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
Expand Down Expand Up @@ -50,12 +51,21 @@ describe('run', () => {
await run();

expect(setLabelsMock).toHaveBeenCalledTimes(1);

expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file'
);
});

it('(with dot: true) adds labels to PRs that match our glob patterns', async () => {
Expand All @@ -77,6 +87,14 @@ describe('run', () => {
issue_number: 123,
labels: ['touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file'
);
});

it('(with dot: false) does not add labels to PRs that do not match our glob patterns', async () => {
Expand All @@ -92,6 +110,8 @@ describe('run', () => {
await run();

expect(setLabelsMock).toHaveBeenCalledTimes(0);
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', '');
});

it('(with dot: true) does not add labels to PRs that do not match our glob patterns', async () => {
Expand Down Expand Up @@ -128,6 +148,8 @@ describe('run', () => {
issue_number: 123,
labels: ['manually-added']
});
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', 'manually-added');
});

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 () => {
Expand All @@ -148,6 +170,11 @@ describe('run', () => {
await run();

expect(setLabelsMock).toHaveBeenCalledTimes(0);
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file,manually-added'
);
});

it('(with sync-labels: false) it only logs the excess labels', async () => {
Expand Down Expand Up @@ -178,6 +205,9 @@ describe('run', () => {
'Maximum of 100 labels allowed. Excess labels: touched-a-pdf-file',
{title: 'Label limit for a PR exceeded'}
);
const allLabels: string = existingLabels.map(i => i.name).join(',');
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', allLabels);
});
});

Expand Down
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ inputs:
default: false
required: false

outputs:
new-labels:
description: 'A comma-separated list of all new labels'
all-labels:
description: 'A comma-separated list of all labels that the PR contains'
runs:
using: 'node16'
main: 'dist/index.js'
14 changes: 9 additions & 5 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ function run() {
core.debug(`fetching changed files for pr #${prNumber}`);
const changedFiles = yield getChangedFiles(client, prNumber);
const labelGlobs = yield getLabelGlobs(client, configPath);
const prLabels = pullRequest.labels.map(label => label.name);
const allLabels = new Set(prLabels);
const preexistingLabels = pullRequest.labels.map(l => l.name);
const allLabels = new Set(preexistingLabels);
for (const [label, globs] of labelGlobs.entries()) {
core.debug(`processing ${label}`);
if (checkGlobs(changedFiles, globs, dot)) {
Expand All @@ -79,12 +79,16 @@ function run() {
allLabels.delete(label);
}
}
const labels = [...allLabels].slice(0, GITHUB_MAX_LABELS);
const labelsToAdd = [...allLabels].slice(0, GITHUB_MAX_LABELS);
const excessLabels = [...allLabels].slice(GITHUB_MAX_LABELS);
try {
if (!isListEqual(prLabels, labels)) {
yield setLabels(client, prNumber, labels);
let newLabels = [];
if (!isListEqual(labelsToAdd, preexistingLabels)) {
yield setLabels(client, prNumber, labelsToAdd);
newLabels = labelsToAdd.filter(l => !preexistingLabels.includes(l));
}
core.setOutput('new-labels', newLabels.join(','));
core.setOutput('all-labels', labelsToAdd.join(','));
if (excessLabels.length) {
core.warning(`Maximum of ${GITHUB_MAX_LABELS} labels allowed. Excess labels: ${excessLabels.join(', ')}`, { title: 'Label limit for a PR exceeded' });
}
Expand Down
16 changes: 11 additions & 5 deletions src/labeler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export async function run() {
configPath
);

const prLabels: string[] = pullRequest.labels.map(label => label.name);
const allLabels: Set<string> = new Set(prLabels);
const preexistingLabels = pullRequest.labels.map(l => l.name);
const allLabels: Set<string> = new Set<string>(preexistingLabels);

for (const [label, globs] of labelGlobs.entries()) {
core.debug(`processing ${label}`);
Expand All @@ -55,14 +55,20 @@ export async function run() {
}
}

const labels = [...allLabels].slice(0, GITHUB_MAX_LABELS);
const labelsToAdd = [...allLabels].slice(0, GITHUB_MAX_LABELS);
const excessLabels = [...allLabels].slice(GITHUB_MAX_LABELS);

try {
if (!isListEqual(prLabels, labels)) {
await setLabels(client, prNumber, labels);
let newLabels: string[] = [];

if (!isListEqual(labelsToAdd, preexistingLabels)) {
await setLabels(client, prNumber, labelsToAdd);
newLabels = labelsToAdd.filter(l => !preexistingLabels.includes(l));
}

core.setOutput('new-labels', newLabels.join(','));
core.setOutput('all-labels', labelsToAdd.join(','));

if (excessLabels.length) {
core.warning(
`Maximum of ${GITHUB_MAX_LABELS} labels allowed. Excess labels: ${excessLabels.join(
Expand Down