Compare commits

...

35 Commits

Author SHA1 Message Date
Matthew Costabile
a9f041ddd4 Merge pull request #142 from timrogers/timrogers/draft-issue
Allow users to add an issue/PR to a board in a different organization
2022-07-21 08:48:51 -04:00
Matthew Costabile
1809404e28 Merge branch 'main' into timrogers/draft-issue 2022-07-21 08:46:09 -04:00
Lukasz Warchol
0af0b18f28 Merge pull request #157 from actions/non-beta-projects
Remove beta references
2022-07-19 18:11:17 +02:00
Lukasz Warchol
c8dd399614 Remove beta references 2022-07-19 15:00:18 +00:00
Matthew Costabile
f111c2aa36 Merge pull request #156 from actions/dependabot/npm_and_yarn/concurrently-7.3.0
build(deps-dev): bump concurrently from 7.2.2 to 7.3.0
2022-07-19 09:30:12 -04:00
Matthew Costabile
12e917e04c Merge pull request #155 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.30.7
build(deps-dev): bump @typescript-eslint/parser from 5.30.6 to 5.30.7
2022-07-19 09:29:58 -04:00
dependabot[bot]
dbe00218fb build(deps-dev): bump concurrently from 7.2.2 to 7.3.0
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 7.2.2 to 7.3.0.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v7.2.2...v7.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-19 13:26:23 +00:00
dependabot[bot]
fa0b958991 build(deps-dev): bump @typescript-eslint/parser from 5.30.6 to 5.30.7
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.30.6 to 5.30.7.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.7/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-19 13:26:00 +00:00
Matthew Costabile
f343062b82 Merge pull request #154 from actions/dependabot/npm_and_yarn/types/node-16.11.45
build(deps-dev): bump @types/node from 16.11.44 to 16.11.45
2022-07-18 10:28:07 -04:00
Matthew Costabile
e639bba4f0 Merge pull request #153 from actions/dependabot/npm_and_yarn/eslint-8.20.0
build(deps-dev): bump eslint from 8.19.0 to 8.20.0
2022-07-18 10:27:53 -04:00
dependabot[bot]
34ff2c7db4 build(deps-dev): bump @types/node from 16.11.44 to 16.11.45
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.11.44 to 16.11.45.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 13:41:32 +00:00
dependabot[bot]
4065956be9 build(deps-dev): bump eslint from 8.19.0 to 8.20.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.19.0 to 8.20.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.19.0...v8.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-18 13:41:25 +00:00
dependabot[bot]
9b0fd13e3f build(deps-dev): bump @types/node from 16.11.43 to 16.11.44 (#151)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.11.43 to 16.11.44.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-15 10:59:26 -03:00
dependabot[bot]
53d95574f4 build(deps-dev): bump eslint-plugin-jest from 26.5.3 to 26.6.0 (#152)
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 26.5.3 to 26.6.0.
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v26.5.3...v26.6.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-15 10:57:38 -03:00
Tim Rogers
ebd4dc568a Fix failing tests 2022-07-15 11:26:04 +01:00
Tim Rogers
9115f344bd Allow users to add an issue/PR to a board in a different organization
At present, this Action only supports adding an issue or pull
request to a project in the *same organization* as the issue or
pull request itself.

This removes that limitation. If the issue/pull request and
project have different owners, then instead of directly
creating a project item, we will instead create a "draft issue"
which will be added to the board.

Fixes #74.
2022-07-15 11:26:04 +01:00
Matthew Costabile
31c3cce717 Merge pull request #150 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.30.6
build(deps-dev): bump @typescript-eslint/parser from 5.30.5 to 5.30.6
2022-07-13 09:46:10 -04:00
dependabot[bot]
c1795be3bc build(deps-dev): bump @typescript-eslint/parser from 5.30.5 to 5.30.6
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.30.5 to 5.30.6.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.6/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-13 13:42:38 +00:00
Matthew Costabile
75ae529d21 Merge pull request #148 from actions/dependabot/npm_and_yarn/types/node-16.11.43
build(deps-dev): bump @types/node from 16.11.42 to 16.11.43
2022-07-11 08:54:13 -04:00
dependabot[bot]
93eba4a2e5 build(deps-dev): bump @types/node from 16.11.42 to 16.11.43
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.11.42 to 16.11.43.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-11 12:52:44 +00:00
Matthew Costabile
5582d9894f Merge pull request #146 from actions/dependabot/npm_and_yarn/eslint-8.19.0
build(deps-dev): bump eslint from 8.18.0 to 8.19.0
2022-07-11 08:52:23 -04:00
Matthew Costabile
97e01d66ef Merge pull request #149 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.30.5
build(deps-dev): bump @typescript-eslint/parser from 5.30.0 to 5.30.5
2022-07-11 08:51:45 -04:00
dependabot[bot]
2a4deb3f9f build(deps-dev): bump @typescript-eslint/parser from 5.30.0 to 5.30.5
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.30.0 to 5.30.5.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.5/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-05 13:37:49 +00:00
dependabot[bot]
458653506b build(deps-dev): bump eslint from 8.18.0 to 8.19.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.18.0 to 8.19.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.18.0...v8.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 13:38:12 +00:00
Matthew Costabile
322721b8cd Merge pull request #144 from actions/dependabot/npm_and_yarn/eslint-plugin-prettier-4.2.1
build(deps-dev): bump eslint-plugin-prettier from 4.1.0 to 4.2.1
2022-06-30 09:48:11 -04:00
Matthew Costabile
601b150078 Merge pull request #145 from actions/dependabot/npm_and_yarn/types/node-16.11.42
build(deps-dev): bump @types/node from 16.11.41 to 16.11.42
2022-06-30 09:44:56 -04:00
dependabot[bot]
665443b5d9 build(deps-dev): bump @types/node from 16.11.41 to 16.11.42
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 16.11.41 to 16.11.42.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-30 13:35:58 +00:00
dependabot[bot]
caae605ffb build(deps-dev): bump eslint-plugin-prettier from 4.1.0 to 4.2.1
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 4.1.0 to 4.2.1.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v4.1.0...v4.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-30 13:35:47 +00:00
Matthew Costabile
5d3a082e24 Merge pull request #143 from actions/fix-tests
fix tests to account for api change
2022-06-30 09:21:52 -04:00
Matthew Costabile
80b198ce77 fix tests to account for api change 2022-06-30 13:13:58 +00:00
Matthew Costabile
92eaaeabac Merge pull request #138 from actions/dependabot/npm_and_yarn/typescript-eslint/parser-5.30.0
build(deps-dev): bump @typescript-eslint/parser from 5.29.0 to 5.30.0
2022-06-28 09:47:01 -04:00
Matthew Costabile
8eedaeb3f8 Merge pull request #137 from actions/dependabot/npm_and_yarn/eslint-plugin-prettier-4.1.0
build(deps-dev): bump eslint-plugin-prettier from 4.0.0 to 4.1.0
2022-06-28 09:46:43 -04:00
dependabot[bot]
3b83e6acf9 build(deps-dev): bump @typescript-eslint/parser from 5.29.0 to 5.30.0
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.29.0 to 5.30.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.30.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-28 13:36:40 +00:00
dependabot[bot]
0bf2f64851 build(deps-dev): bump eslint-plugin-prettier from 4.0.0 to 4.1.0
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v4.0.0...v4.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-28 13:36:28 +00:00
Lukasz Warchol
ce9d751c8c Update legacy version reference in the Readme 2022-06-28 14:21:39 +02:00
9 changed files with 431 additions and 185 deletions

View File

@@ -18,3 +18,5 @@ jobs:
npm install npm install
- run: | - run: |
npm run build npm run build
- run: |
npm run test

View File

@@ -1,17 +1,13 @@
# actions/add-to-project # actions/add-to-project
Use this action to automatically add the current issue or pull request to a GitHub project. Use this action to automatically add the current issue or pull request to a [GitHub project](https://docs.github.com/en/issues/trying-out-the-new-projects-experience/about-projects).
Note that this is for [GitHub projects Note that this action does not support [GitHub projects (classic)](https://docs.github.com/en/issues/organizing-your-work-with-project-boards).
(beta)](https://docs.github.com/en/issues/trying-out-the-new-projects-experience/about-projects),
not the original GitHub projects.
## Current Status ## Current Status
[![build-test](https://github.com/actions/add-to-project/actions/workflows/test.yml/badge.svg)](https://github.com/actions/add-to-project/actions/workflows/test.yml) [![build-test](https://github.com/actions/add-to-project/actions/workflows/test.yml/badge.svg)](https://github.com/actions/add-to-project/actions/workflows/test.yml)
> **NOTE:** This Action (currently) only supports auto-adding Issues/Pull Requests to a Project which lives in the same organization as your target Repository. > **NOTE:** ⚠️ This action no longer uses the deprecated ProjectNext API. If you are looking for the old version of that action, use version [v0.0.5](https://github.com/actions/add-to-project/releases/tag/v0.0.5).
> **NOTE:** This action no longer uses the deprecated ProjectNext API. If you are looking for the old version of that action, use version [v0.0.3](https://github.com/actions/add-to-project/releases/tag/v0.0.3).
## Usage ## Usage
@@ -42,6 +38,8 @@ jobs:
steps: steps:
- uses: actions/add-to-project@RELEASE_VERSION - uses: actions/add-to-project@RELEASE_VERSION
with: with:
# You can target a repository in a different organization
# to the issue
project-url: https://github.com/orgs/<orgName>/projects/<projectNumber> project-url: https://github.com/orgs/<orgName>/projects/<projectNumber>
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labeled: bug, needs-triage labeled: bug, needs-triage

View File

@@ -12,7 +12,7 @@ describe('addToProject', () => {
beforeEach(() => { beforeEach(() => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token' 'github-token': 'gh_token'
}) })
@@ -24,7 +24,22 @@ describe('addToProject', () => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
test('adds an issue to the project', async () => { test('adds an issue from the same organization to the project', async () => {
github.context.payload = {
issue: {
number: 1,
labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
}
}
mockGraphQL( mockGraphQL(
{ {
test: /getProject/, test: /getProject/,
@@ -53,9 +68,53 @@ describe('addToProject', () => {
expect(outputs.itemId).toEqual('project-item-id') expect(outputs.itemId).toEqual('project-item-id')
}) })
test('adds an issue from a different organization to the project', async () => {
github.context.payload = {
issue: {
number: 2221,
labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/octokit/octokit.js/issues/2221'
},
repository: {
name: 'octokit.js',
owner: {
login: 'octokit'
}
}
}
mockGraphQL(
{
test: /getProject/,
return: {
organization: {
projectV2: {
id: 'project-id'
}
}
}
},
{
test: /addProjectV2DraftIssue/,
return: {
addProjectV2DraftIssue: {
projectItem: {
id: 'project-item-id'
}
}
}
}
)
await addToProject()
expect(outputs.itemId).toEqual('project-item-id')
})
test('adds matching issues with a label filter without label-operator', async () => { test('adds matching issues with a label filter without label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new' labeled: 'bug, new'
}) })
@@ -63,7 +122,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}] labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -97,7 +164,7 @@ describe('addToProject', () => {
test('adds matching pull-requests with a label filter without label-operator', async () => { test('adds matching pull-requests with a label filter without label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new' labeled: 'bug, new'
}) })
@@ -106,7 +173,15 @@ describe('addToProject', () => {
// eslint-disable-next-line camelcase // eslint-disable-next-line camelcase
pull_request: { pull_request: {
number: 1, number: 1,
labels: [{name: 'bug'}] labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/pull/136'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -140,7 +215,7 @@ describe('addToProject', () => {
test('does not add un-matching issues with a label filter without label-operator', async () => { test('does not add un-matching issues with a label filter without label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug' labeled: 'bug'
}) })
@@ -148,7 +223,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [] labels: [],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -161,7 +244,7 @@ describe('addToProject', () => {
test('adds matching issues with labels filter with AND label-operator', async () => { test('adds matching issues with labels filter with AND label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new', labeled: 'bug, new',
'label-operator': 'AND' 'label-operator': 'AND'
@@ -170,7 +253,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}, {name: 'new'}] labels: [{name: 'bug'}, {name: 'new'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -204,7 +295,7 @@ describe('addToProject', () => {
test('does not add un-matching issues with labels filter with AND label-operator', async () => { test('does not add un-matching issues with labels filter with AND label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new', labeled: 'bug, new',
'label-operator': 'AND' 'label-operator': 'AND'
@@ -213,7 +304,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}, {name: 'other'}] labels: [{name: 'bug'}, {name: 'other'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -226,7 +325,7 @@ describe('addToProject', () => {
test('does not add matching issues with labels filter with NOT label-operator', async () => { test('does not add matching issues with labels filter with NOT label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new', labeled: 'bug, new',
'label-operator': 'NOT' 'label-operator': 'NOT'
@@ -235,7 +334,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}] labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -248,7 +355,7 @@ describe('addToProject', () => {
test('adds issues that do not have labels present in the label list with NOT label-operator', async () => { test('adds issues that do not have labels present in the label list with NOT label-operator', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new', labeled: 'bug, new',
'label-operator': 'NOT' 'label-operator': 'NOT'
@@ -257,7 +364,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'other'}] labels: [{name: 'other'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -266,17 +381,17 @@ describe('addToProject', () => {
test: /getProject/, test: /getProject/,
return: { return: {
organization: { organization: {
projectNext: { projectV2: {
id: 'project-next-id' id: 'project-next-id'
} }
} }
} }
}, },
{ {
test: /addProjectNextItem/, test: /addProjectV2ItemById/,
return: { return: {
addProjectNextItem: { addProjectV2ItemById: {
projectNextItem: { item: {
id: 'project-next-item-id' id: 'project-next-item-id'
} }
} }
@@ -291,7 +406,7 @@ describe('addToProject', () => {
test('adds matching issues with multiple label filters', async () => { test('adds matching issues with multiple label filters', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'accessibility,backend,bug' labeled: 'accessibility,backend,bug'
}) })
@@ -299,7 +414,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'accessibility'}, {name: 'backend'}] labels: [{name: 'accessibility'}, {name: 'backend'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -331,13 +454,15 @@ describe('addToProject', () => {
await addToProject() await addToProject()
expect(gqlMock).toHaveBeenCalled() expect(gqlMock).toHaveBeenCalled()
expect(infoSpy).not.toHaveBeenCalled() expect(infoSpy).toHaveBeenCalledWith('Creating project item')
// We shouldn't have any logs relating to the issue being skipped
expect(infoSpy.mock.calls.length).toEqual(1)
expect(outputs.itemId).toEqual('project-item-id') expect(outputs.itemId).toEqual('project-item-id')
}) })
test('does not add un-matching issues with multiple label filters', async () => { test('does not add un-matching issues with multiple label filters', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'accessibility, backend, bug' labeled: 'accessibility, backend, bug'
}) })
@@ -345,7 +470,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'data'}, {name: 'frontend'}, {name: 'improvement'}] labels: [{name: 'data'}, {name: 'frontend'}, {name: 'improvement'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -360,7 +493,7 @@ describe('addToProject', () => {
test('handles spaces and extra commas gracefully in label filter input', async () => { test('handles spaces and extra commas gracefully in label filter input', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'accessibility , backend ,, . , bug' labeled: 'accessibility , backend ,, . , bug'
}) })
@@ -369,7 +502,15 @@ describe('addToProject', () => {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'accessibility'}, {name: 'backend'}, {name: 'bug'}], labels: [{name: 'accessibility'}, {name: 'backend'}, {name: 'bug'}],
'label-operator': 'AND' 'label-operator': 'AND',
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -401,7 +542,9 @@ describe('addToProject', () => {
await addToProject() await addToProject()
expect(gqlMock).toHaveBeenCalled() expect(gqlMock).toHaveBeenCalled()
expect(infoSpy).not.toHaveBeenCalled() expect(infoSpy).toHaveBeenCalledWith('Creating project item')
// We shouldn't have any logs relating to the issue being skipped
expect(infoSpy.mock.calls.length).toEqual(1)
expect(outputs.itemId).toEqual('project-item-id') expect(outputs.itemId).toEqual('project-item-id')
}) })
@@ -414,7 +557,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [] labels: [],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -436,7 +587,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [] labels: [],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -451,7 +610,7 @@ describe('addToProject', () => {
test('constructs the correct graphQL query given an organization owner', async () => { test('constructs the correct graphQL query given an organization owner', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'bug, new' labeled: 'bug, new'
}) })
@@ -459,7 +618,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}] labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -488,8 +655,8 @@ describe('addToProject', () => {
await addToProject() await addToProject()
expect(gqlMock).toHaveBeenNthCalledWith(1, expect.stringContaining('organization(login: $ownerName)'), { expect(gqlMock).toHaveBeenNthCalledWith(1, expect.stringContaining('organization(login: $projectOwnerName)'), {
ownerName: 'github', projectOwnerName: 'actions',
projectNumber: 1 projectNumber: 1
}) })
}) })
@@ -504,7 +671,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'bug'}] labels: [{name: 'bug'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/monalisa/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'monalisa'
}
} }
} }
@@ -533,15 +708,15 @@ describe('addToProject', () => {
await addToProject() await addToProject()
expect(gqlMock).toHaveBeenNthCalledWith(1, expect.stringContaining('user(login: $ownerName)'), { expect(gqlMock).toHaveBeenNthCalledWith(1, expect.stringContaining('user(login: $projectOwnerName)'), {
ownerName: 'monalisa', projectOwnerName: 'monalisa',
projectNumber: 1 projectNumber: 1
}) })
}) })
test('compares labels case-insensitively', async () => { test('compares labels case-insensitively', async () => {
mockGetInput({ mockGetInput({
'project-url': 'https://github.com/orgs/github/projects/1', 'project-url': 'https://github.com/orgs/actions/projects/1',
'github-token': 'gh_token', 'github-token': 'gh_token',
labeled: 'FOO, Bar, baz', labeled: 'FOO, Bar, baz',
'label-operator': 'AND' 'label-operator': 'AND'
@@ -550,7 +725,15 @@ describe('addToProject', () => {
github.context.payload = { github.context.payload = {
issue: { issue: {
number: 1, number: 1,
labels: [{name: 'foo'}, {name: 'BAR'}, {name: 'baz'}] labels: [{name: 'foo'}, {name: 'BAR'}, {name: 'baz'}],
// eslint-disable-next-line camelcase
html_url: 'https://github.com/actions/add-to-project/issues/74'
},
repository: {
name: 'add-to-project',
owner: {
login: 'actions'
}
} }
} }
@@ -559,17 +742,17 @@ describe('addToProject', () => {
test: /getProject/, test: /getProject/,
return: { return: {
organization: { organization: {
projectNext: { projectV2: {
id: 'project-next-id' id: 'project-next-id'
} }
} }
} }
}, },
{ {
test: /addProjectNextItem/, test: /addProjectV2ItemById/,
return: { return: {
addProjectNextItem: { addProjectV2ItemById: {
projectNextItem: { item: {
id: 'project-next-item-id' id: 'project-next-item-id'
} }
} }

View File

@@ -1,5 +1,5 @@
name: Add To GitHub Projects Beta name: Add To GitHub projects
description: Automatically add issues and PRs to GitHub projects beta description: Automatically add issues and PRs to GitHub projects
author: GitHub author: GitHub
branding: branding:
icon: table icon: table

68
dist/index.js generated vendored
View File

@@ -46,7 +46,7 @@ const github = __importStar(__nccwpck_require__(5438));
// https://github.com/orgs|users/<ownerName>/projects/<projectNumber> // https://github.com/orgs|users/<ownerName>/projects/<projectNumber>
const urlParse = /^(?:https:\/\/)?github\.com\/(?<ownerType>orgs|users)\/(?<ownerName>[^/]+)\/projects\/(?<projectNumber>\d+)/; const urlParse = /^(?:https:\/\/)?github\.com\/(?<ownerType>orgs|users)\/(?<ownerName>[^/]+)\/projects\/(?<projectNumber>\d+)/;
function addToProject() { function addToProject() {
var _a, _b, _c, _d, _e, _f, _g, _h; var _a, _b, _c, _d, _e, _f, _g, _h, _j;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const projectUrl = core.getInput('project-url', { required: true }); const projectUrl = core.getInput('project-url', { required: true });
const ghToken = core.getInput('github-token', { required: true }); const ghToken = core.getInput('github-token', { required: true });
@@ -57,9 +57,10 @@ function addToProject() {
.filter(l => l.length > 0)) !== null && _a !== void 0 ? _a : []; .filter(l => l.length > 0)) !== null && _a !== void 0 ? _a : [];
const labelOperator = core.getInput('label-operator').trim().toLocaleLowerCase(); const labelOperator = core.getInput('label-operator').trim().toLocaleLowerCase();
const octokit = github.getOctokit(ghToken); const octokit = github.getOctokit(ghToken);
const urlMatch = projectUrl.match(urlParse);
const issue = (_b = github.context.payload.issue) !== null && _b !== void 0 ? _b : github.context.payload.pull_request; const issue = (_b = github.context.payload.issue) !== null && _b !== void 0 ? _b : github.context.payload.pull_request;
const issueLabels = ((_c = issue === null || issue === void 0 ? void 0 : issue.labels) !== null && _c !== void 0 ? _c : []).map((l) => l.name.toLowerCase()); const issueLabels = ((_c = issue === null || issue === void 0 ? void 0 : issue.labels) !== null && _c !== void 0 ? _c : []).map((l) => l.name.toLowerCase());
const issueOwnerName = (_d = github.context.payload.repository) === null || _d === void 0 ? void 0 : _d.owner.login;
core.debug(`Issue/PR owner: ${issueOwnerName}`);
// Ensure the issue matches our `labeled` filter based on the label-operator. // Ensure the issue matches our `labeled` filter based on the label-operator.
if (labelOperator === 'and') { if (labelOperator === 'and') {
if (!labeled.every(l => issueLabels.includes(l))) { if (!labeled.every(l => issueLabels.includes(l))) {
@@ -80,45 +81,68 @@ function addToProject() {
} }
} }
core.debug(`Project URL: ${projectUrl}`); core.debug(`Project URL: ${projectUrl}`);
const urlMatch = projectUrl.match(urlParse);
if (!urlMatch) { if (!urlMatch) {
throw new Error(`Invalid project URL: ${projectUrl}. Project URL should match the format https://github.com/<orgs-or-users>/<ownerName>/projects/<projectNumber>`); throw new Error(`Invalid project URL: ${projectUrl}. Project URL should match the format https://github.com/<orgs-or-users>/<ownerName>/projects/<projectNumber>`);
} }
const ownerName = (_d = urlMatch.groups) === null || _d === void 0 ? void 0 : _d.ownerName; const projectOwnerName = (_e = urlMatch.groups) === null || _e === void 0 ? void 0 : _e.ownerName;
const projectNumber = parseInt((_f = (_e = urlMatch.groups) === null || _e === void 0 ? void 0 : _e.projectNumber) !== null && _f !== void 0 ? _f : '', 10); const projectNumber = parseInt((_g = (_f = urlMatch.groups) === null || _f === void 0 ? void 0 : _f.projectNumber) !== null && _g !== void 0 ? _g : '', 10);
const ownerType = (_g = urlMatch.groups) === null || _g === void 0 ? void 0 : _g.ownerType; const ownerType = (_h = urlMatch.groups) === null || _h === void 0 ? void 0 : _h.ownerType;
const ownerTypeQuery = mustGetOwnerTypeQuery(ownerType); const ownerTypeQuery = mustGetOwnerTypeQuery(ownerType);
core.debug(`Org name: ${ownerName}`); core.debug(`Project owner: ${projectOwnerName}`);
core.debug(`Project number: ${projectNumber}`); core.debug(`Project number: ${projectNumber}`);
core.debug(`Owner type: ${ownerType}`); core.debug(`Project owner type: ${ownerType}`);
// First, use the GraphQL API to request the project's node ID. // First, use the GraphQL API to request the project's node ID.
const idResp = yield octokit.graphql(`query getProject($ownerName: String!, $projectNumber: Int!) { const idResp = yield octokit.graphql(`query getProject($projectOwnerName: String!, $projectNumber: Int!) {
${ownerTypeQuery}(login: $ownerName) { ${ownerTypeQuery}(login: $projectOwnerName) {
projectV2(number: $projectNumber) { projectV2(number: $projectNumber) {
id id
} }
} }
}`, { }`, {
ownerName, projectOwnerName,
projectNumber projectNumber
}); });
const projectId = (_h = idResp[ownerTypeQuery]) === null || _h === void 0 ? void 0 : _h.projectV2.id; const projectId = (_j = idResp[ownerTypeQuery]) === null || _j === void 0 ? void 0 : _j.projectV2.id;
const contentId = issue === null || issue === void 0 ? void 0 : issue.node_id; const contentId = issue === null || issue === void 0 ? void 0 : issue.node_id;
core.debug(`Project node ID: ${projectId}`); core.debug(`Project node ID: ${projectId}`);
core.debug(`Content ID: ${contentId}`); core.debug(`Content ID: ${contentId}`);
// Next, use the GraphQL API to add the issue to the project. // Next, use the GraphQL API to add the issue to the project.
const addResp = yield octokit.graphql(`mutation addIssueToProject($input: AddProjectV2ItemByIdInput!) { // If the issue has the same owner as the project, we can directly
addProjectV2ItemById(input: $input) { // add a project item. Otherwise, we add a draft issue.
item { if (issueOwnerName === projectOwnerName) {
id core.info('Creating project item');
const addResp = yield octokit.graphql(`mutation addIssueToProject($input: AddProjectV2ItemByIdInput!) {
addProjectV2ItemById(input: $input) {
item {
id
}
} }
} }`, {
}`, { input: {
input: { projectId,
contentId
}
});
core.setOutput('itemId', addResp.addProjectV2ItemById.item.id);
}
else {
core.info('Creating draft issue in project');
const addResp = yield octokit.graphql(`mutation addDraftIssueToProject($projectId: ID!, $title: String!) {
addProjectV2DraftIssue(input: {
projectId: $projectId,
title: $title
}) {
projectItem {
id
}
}
}`, {
projectId, projectId,
contentId title: issue === null || issue === void 0 ? void 0 : issue.html_url
} });
}); core.setOutput('itemId', addResp.addProjectV2DraftIssue.projectItem.id);
core.setOutput('itemId', addResp.addProjectV2ItemById.item.id); }
}); });
} }
exports.addToProject = addToProject; exports.addToProject = addToProject;

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

166
package-lock.json generated
View File

@@ -15,14 +15,14 @@
"devDependencies": { "devDependencies": {
"@github/prettier-config": "^0.0.4", "@github/prettier-config": "^0.0.4",
"@types/jest": "^27.5.0", "@types/jest": "^27.5.0",
"@types/node": "~16.11.41", "@types/node": "~16.11.45",
"@typescript-eslint/parser": "^5.29.0", "@typescript-eslint/parser": "^5.30.7",
"@vercel/ncc": "^0.34.0", "@vercel/ncc": "^0.34.0",
"concurrently": "^7.2.2", "concurrently": "^7.3.0",
"eslint": "^8.18.0", "eslint": "^8.20.0",
"eslint-plugin-github": "^4.3.6", "eslint-plugin-github": "^4.3.6",
"eslint-plugin-jest": "^26.5.3", "eslint-plugin-jest": "^26.6.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.2.1",
"jest": "^27.5.1", "jest": "^27.5.1",
"prettier": "2.7.1", "prettier": "2.7.1",
"ts-jest": "^27.1.4", "ts-jest": "^27.1.4",
@@ -1367,9 +1367,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.11.41", "version": "16.11.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.41.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.45.tgz",
"integrity": "sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ==", "integrity": "sha512-3rKg/L5x0rofKuuUt5zlXzOnKyIHXmIu5R8A0TuNDMF2062/AOIDBciFIjToLEJ/9F9DzkHNot+BpNsMI1OLdQ==",
"dev": true "dev": true
}, },
"node_modules/@types/prettier": { "node_modules/@types/prettier": {
@@ -1448,14 +1448,14 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
"integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", "integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "5.29.0", "@typescript-eslint/scope-manager": "5.30.7",
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/typescript-estree": "5.29.0", "@typescript-eslint/typescript-estree": "5.30.7",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -1475,13 +1475,13 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz",
"integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", "integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/visitor-keys": "5.29.0" "@typescript-eslint/visitor-keys": "5.30.7"
}, },
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1492,9 +1492,9 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz",
"integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", "integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1505,13 +1505,13 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz",
"integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", "integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/visitor-keys": "5.29.0", "@typescript-eslint/visitor-keys": "5.30.7",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -1532,12 +1532,12 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz",
"integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", "integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
}, },
"engines": { "engines": {
@@ -2263,9 +2263,9 @@
"dev": true "dev": true
}, },
"node_modules/concurrently": { "node_modules/concurrently": {
"version": "7.2.2", "version": "7.3.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.2.2.tgz", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.3.0.tgz",
"integrity": "sha512-DcQkI0ruil5BA/g7Xy3EWySGrFJovF5RYAYxwGvv9Jf9q9B1v3jPFP2tl6axExNf1qgF30kjoNYrangZ0ey4Aw==", "integrity": "sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chalk": "^4.1.0", "chalk": "^4.1.0",
@@ -2659,9 +2659,9 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "8.18.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz",
"integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint/eslintrc": "^1.3.0", "@eslint/eslintrc": "^1.3.0",
@@ -2901,9 +2901,9 @@
"dev": true "dev": true
}, },
"node_modules/eslint-plugin-jest": { "node_modules/eslint-plugin-jest": {
"version": "26.5.3", "version": "26.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.5.3.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.6.0.tgz",
"integrity": "sha512-sICclUqJQnR1bFRZGLN2jnSVsYOsmPYYnroGCIMVSvTS3y8XR3yjzy1EcTQmk6typ5pRgyIWzbjqxK6cZHEZuQ==", "integrity": "sha512-f8n46/97ZFdU4KqeQYqO8AEVGIhHWvkpgNBWHH3jrM28/y8llnbf3IjfIKv6p2pZIMinK1PCqbbROxs9Eud02Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/utils": "^5.10.0" "@typescript-eslint/utils": "^5.10.0"
@@ -2934,15 +2934,15 @@
} }
}, },
"node_modules/eslint-plugin-prettier": { "node_modules/eslint-plugin-prettier": {
"version": "4.0.0", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
"integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"prettier-linter-helpers": "^1.0.0" "prettier-linter-helpers": "^1.0.0"
}, },
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=12.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": ">=7.28.0", "eslint": ">=7.28.0",
@@ -7577,9 +7577,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "16.11.41", "version": "16.11.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.41.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.45.tgz",
"integrity": "sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ==", "integrity": "sha512-3rKg/L5x0rofKuuUt5zlXzOnKyIHXmIu5R8A0TuNDMF2062/AOIDBciFIjToLEJ/9F9DzkHNot+BpNsMI1OLdQ==",
"dev": true "dev": true
}, },
"@types/prettier": { "@types/prettier": {
@@ -7638,41 +7638,41 @@
} }
}, },
"@typescript-eslint/parser": { "@typescript-eslint/parser": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
"integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", "integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "5.29.0", "@typescript-eslint/scope-manager": "5.30.7",
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/typescript-estree": "5.29.0", "@typescript-eslint/typescript-estree": "5.30.7",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": { "@typescript-eslint/scope-manager": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz",
"integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", "integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/visitor-keys": "5.29.0" "@typescript-eslint/visitor-keys": "5.30.7"
} }
}, },
"@typescript-eslint/types": { "@typescript-eslint/types": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz",
"integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", "integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==",
"dev": true "dev": true
}, },
"@typescript-eslint/typescript-estree": { "@typescript-eslint/typescript-estree": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz",
"integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", "integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"@typescript-eslint/visitor-keys": "5.29.0", "@typescript-eslint/visitor-keys": "5.30.7",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -7681,12 +7681,12 @@
} }
}, },
"@typescript-eslint/visitor-keys": { "@typescript-eslint/visitor-keys": {
"version": "5.29.0", "version": "5.30.7",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz",
"integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", "integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/types": "5.29.0", "@typescript-eslint/types": "5.30.7",
"eslint-visitor-keys": "^3.3.0" "eslint-visitor-keys": "^3.3.0"
} }
}, },
@@ -8204,9 +8204,9 @@
"dev": true "dev": true
}, },
"concurrently": { "concurrently": {
"version": "7.2.2", "version": "7.3.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.2.2.tgz", "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.3.0.tgz",
"integrity": "sha512-DcQkI0ruil5BA/g7Xy3EWySGrFJovF5RYAYxwGvv9Jf9q9B1v3jPFP2tl6axExNf1qgF30kjoNYrangZ0ey4Aw==", "integrity": "sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA==",
"dev": true, "dev": true,
"requires": { "requires": {
"chalk": "^4.1.0", "chalk": "^4.1.0",
@@ -8504,9 +8504,9 @@
} }
}, },
"eslint": { "eslint": {
"version": "8.18.0", "version": "8.20.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.20.0.tgz",
"integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", "integrity": "sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@eslint/eslintrc": "^1.3.0", "@eslint/eslintrc": "^1.3.0",
@@ -8759,9 +8759,9 @@
} }
}, },
"eslint-plugin-jest": { "eslint-plugin-jest": {
"version": "26.5.3", "version": "26.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.5.3.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.6.0.tgz",
"integrity": "sha512-sICclUqJQnR1bFRZGLN2jnSVsYOsmPYYnroGCIMVSvTS3y8XR3yjzy1EcTQmk6typ5pRgyIWzbjqxK6cZHEZuQ==", "integrity": "sha512-f8n46/97ZFdU4KqeQYqO8AEVGIhHWvkpgNBWHH3jrM28/y8llnbf3IjfIKv6p2pZIMinK1PCqbbROxs9Eud02Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"@typescript-eslint/utils": "^5.10.0" "@typescript-eslint/utils": "^5.10.0"
@@ -8774,9 +8774,9 @@
"dev": true "dev": true
}, },
"eslint-plugin-prettier": { "eslint-plugin-prettier": {
"version": "4.0.0", "version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
"integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"prettier-linter-helpers": "^1.0.0" "prettier-linter-helpers": "^1.0.0"

View File

@@ -14,14 +14,14 @@
"devDependencies": { "devDependencies": {
"@github/prettier-config": "^0.0.4", "@github/prettier-config": "^0.0.4",
"@types/jest": "^27.5.0", "@types/jest": "^27.5.0",
"@types/node": "~16.11.41", "@types/node": "~16.11.45",
"@typescript-eslint/parser": "^5.29.0", "@typescript-eslint/parser": "^5.30.7",
"@vercel/ncc": "^0.34.0", "@vercel/ncc": "^0.34.0",
"concurrently": "^7.2.2", "concurrently": "^7.3.0",
"eslint": "^8.18.0", "eslint": "^8.20.0",
"eslint-plugin-github": "^4.3.6", "eslint-plugin-github": "^4.3.6",
"eslint-plugin-jest": "^26.5.3", "eslint-plugin-jest": "^26.6.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.2.1",
"jest": "^27.5.1", "jest": "^27.5.1",
"prettier": "2.7.1", "prettier": "2.7.1",
"ts-jest": "^27.1.4", "ts-jest": "^27.1.4",

View File

@@ -28,6 +28,14 @@ interface ProjectAddItemResponse {
} }
} }
interface ProjectV2AddDraftIssueResponse {
addProjectV2DraftIssue: {
projectItem: {
id: string
}
}
}
export async function addToProject(): Promise<void> { export async function addToProject(): Promise<void> {
const projectUrl = core.getInput('project-url', {required: true}) const projectUrl = core.getInput('project-url', {required: true})
const ghToken = core.getInput('github-token', {required: true}) const ghToken = core.getInput('github-token', {required: true})
@@ -41,9 +49,11 @@ export async function addToProject(): Promise<void> {
const octokit = github.getOctokit(ghToken) const octokit = github.getOctokit(ghToken)
const urlMatch = projectUrl.match(urlParse)
const issue = github.context.payload.issue ?? github.context.payload.pull_request const issue = github.context.payload.issue ?? github.context.payload.pull_request
const issueLabels: string[] = (issue?.labels ?? []).map((l: {name: string}) => l.name.toLowerCase()) const issueLabels: string[] = (issue?.labels ?? []).map((l: {name: string}) => l.name.toLowerCase())
const issueOwnerName = github.context.payload.repository?.owner.login
core.debug(`Issue/PR owner: ${issueOwnerName}`)
// Ensure the issue matches our `labeled` filter based on the label-operator. // Ensure the issue matches our `labeled` filter based on the label-operator.
if (labelOperator === 'and') { if (labelOperator === 'and') {
@@ -65,32 +75,34 @@ export async function addToProject(): Promise<void> {
core.debug(`Project URL: ${projectUrl}`) core.debug(`Project URL: ${projectUrl}`)
const urlMatch = projectUrl.match(urlParse)
if (!urlMatch) { if (!urlMatch) {
throw new Error( throw new Error(
`Invalid project URL: ${projectUrl}. Project URL should match the format https://github.com/<orgs-or-users>/<ownerName>/projects/<projectNumber>` `Invalid project URL: ${projectUrl}. Project URL should match the format https://github.com/<orgs-or-users>/<ownerName>/projects/<projectNumber>`
) )
} }
const ownerName = urlMatch.groups?.ownerName const projectOwnerName = urlMatch.groups?.ownerName
const projectNumber = parseInt(urlMatch.groups?.projectNumber ?? '', 10) const projectNumber = parseInt(urlMatch.groups?.projectNumber ?? '', 10)
const ownerType = urlMatch.groups?.ownerType const ownerType = urlMatch.groups?.ownerType
const ownerTypeQuery = mustGetOwnerTypeQuery(ownerType) const ownerTypeQuery = mustGetOwnerTypeQuery(ownerType)
core.debug(`Org name: ${ownerName}`) core.debug(`Project owner: ${projectOwnerName}`)
core.debug(`Project number: ${projectNumber}`) core.debug(`Project number: ${projectNumber}`)
core.debug(`Owner type: ${ownerType}`) core.debug(`Project owner type: ${ownerType}`)
// First, use the GraphQL API to request the project's node ID. // First, use the GraphQL API to request the project's node ID.
const idResp = await octokit.graphql<ProjectNodeIDResponse>( const idResp = await octokit.graphql<ProjectNodeIDResponse>(
`query getProject($ownerName: String!, $projectNumber: Int!) { `query getProject($projectOwnerName: String!, $projectNumber: Int!) {
${ownerTypeQuery}(login: $ownerName) { ${ownerTypeQuery}(login: $projectOwnerName) {
projectV2(number: $projectNumber) { projectV2(number: $projectNumber) {
id id
} }
} }
}`, }`,
{ {
ownerName, projectOwnerName,
projectNumber projectNumber
} }
) )
@@ -102,23 +114,50 @@ export async function addToProject(): Promise<void> {
core.debug(`Content ID: ${contentId}`) core.debug(`Content ID: ${contentId}`)
// Next, use the GraphQL API to add the issue to the project. // Next, use the GraphQL API to add the issue to the project.
const addResp = await octokit.graphql<ProjectAddItemResponse>( // If the issue has the same owner as the project, we can directly
`mutation addIssueToProject($input: AddProjectV2ItemByIdInput!) { // add a project item. Otherwise, we add a draft issue.
addProjectV2ItemById(input: $input) { if (issueOwnerName === projectOwnerName) {
item { core.info('Creating project item')
id
const addResp = await octokit.graphql<ProjectAddItemResponse>(
`mutation addIssueToProject($input: AddProjectV2ItemByIdInput!) {
addProjectV2ItemById(input: $input) {
item {
id
}
}
}`,
{
input: {
projectId,
contentId
} }
} }
}`, )
{
input: {
projectId,
contentId
}
}
)
core.setOutput('itemId', addResp.addProjectV2ItemById.item.id) core.setOutput('itemId', addResp.addProjectV2ItemById.item.id)
} else {
core.info('Creating draft issue in project')
const addResp = await octokit.graphql<ProjectV2AddDraftIssueResponse>(
`mutation addDraftIssueToProject($projectId: ID!, $title: String!) {
addProjectV2DraftIssue(input: {
projectId: $projectId,
title: $title
}) {
projectItem {
id
}
}
}`,
{
projectId,
title: issue?.html_url
}
)
core.setOutput('itemId', addResp.addProjectV2DraftIssue.projectItem.id)
}
} }
export function mustGetOwnerTypeQuery(ownerType?: string): 'organization' | 'user' { export function mustGetOwnerTypeQuery(ownerType?: string): 'organization' | 'user' {