Compare commits

..

5 Commits

Author SHA1 Message Date
semantic-release-bot
bf559f8544 build(release): 3.0.0-beta.2 [skip ci]
# [3.0.0-beta.2](https://github.com/actions/create-github-app-token/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2025-08-22)

### Bug Fixes

* remove custom proxy handling ([#143](https://github.com/actions/create-github-app-token/issues/143)) ([cda91bf](cda91bf2b9)), closes [#134](https://github.com/actions/create-github-app-token/issues/134)
2025-08-22 19:16:51 +00:00
Parker Brown
cda91bf2b9 fix: remove custom proxy handling (#143)
Undici has added native support for proxy handling, so it is no longer necessary for us to have our own custom proxy handling.

Reverts #102 and resolves #134.
2025-08-22 12:16:16 -07:00
Parker Brown
2ae58da528 Disable semantic-release-plugin-github-breaking-version-tag
https://github.com/gr2m/semantic-release-plugin-update-version-in-files/issues/52
2025-08-15 13:03:02 -07:00
semantic-release-bot
fb1c7fda2b build(release): 3.0.0-beta.1 [skip ci]
# [3.0.0-beta.1](https://github.com/actions/create-github-app-token/compare/v2.1.1...v3.0.0-beta.1) (2025-08-15)

* feat!: node 24 support ([#275](https://github.com/actions/create-github-app-token/issues/275)) ([6178938](61789386cb))

### BREAKING CHANGES

* Requires [Actions Runner v2.327.1](https://github.com/actions/runner/releases/tag/v2.327.1) or later if you are using a self-hosted runner.
2025-08-15 19:55:36 +00:00
Salman Chishti
61789386cb feat!: node 24 support (#275)
BREAKING CHANGE: Requires [Actions Runner v2.327.1](https://github.com/actions/runner/releases/tag/v2.327.1) or later if you are using a self-hosted runner.

---------

Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com>
2025-08-15 12:55:04 -07:00
28 changed files with 25791 additions and 26172 deletions

View File

@@ -12,6 +12,6 @@ jobs:
id-token: write id-token: write
packages: write packages: write
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v5
- name: Publish Immutable Action - name: Publish Immutable Action
uses: actions/publish-immutable-action@v0.0.4 uses: actions/publish-immutable-action@v0.0.4

View File

@@ -18,13 +18,14 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
# build local version to create token # build local version to create token
- uses: actions/checkout@v6 - uses: actions/checkout@v5
with: with:
persist-credentials: false persist-credentials: false
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: package.json
cache: 'npm'
- run: npm ci - run: npm ci
- run: npm run build - run: npm run build

View File

@@ -1,34 +0,0 @@
# This workflow warns and then closes issues that have had no activity for a specified amount of time.
# https://github.com/actions/stale
name: Stale
on:
workflow_dispatch:
schedule:
# 00:00 UTC on Mondays
- cron: '0 0 * * 1'
permissions:
issues: write
pull-requests: write
env:
DAYS_BEFORE_STALE: 180
DAYS_BEFORE_CLOSE: 60
STALE_LABEL: 'stale'
STALE_LABEL_URL: ${{github.server_url}}/${{github.repository}}/labels/stale
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
operations-per-run: 100
days-before-stale: ${{ env.DAYS_BEFORE_STALE }}
days-before-close: ${{ env.DAYS_BEFORE_CLOSE }}
stale-issue-label: ${{ env.STALE_LABEL }}
stale-pr-label: ${{ env.STALE_LABEL }}
stale-issue-message: 'This issue has been marked ${{ env.STALE_LABEL_URL }} because it has been open for ${{ env.DAYS_BEFORE_STALE }} days with no activity. Please close this issue if it is no longer needed. If this issue is still relevant and you would like it to remain open, simply update it within the next ${{ env.DAYS_BEFORE_CLOSE }} days.'
stale-pr-message: 'This pull request has been marked ${{ env.STALE_LABEL_URL }} because it has been open for ${{ env.DAYS_BEFORE_STALE }} days with no activity. Please close this pull request if it is no longer needed. If this pull request is still relevant and you would like it to remain open, simply update it within the next ${{ env.DAYS_BEFORE_CLOSE }} days.'

View File

@@ -4,9 +4,7 @@ on:
push: push:
branches: branches:
- main - main
- beta
pull_request: pull_request:
merge_group:
workflow_dispatch: workflow_dispatch:
concurrency: concurrency:
@@ -18,28 +16,30 @@ permissions:
jobs: jobs:
integration: integration:
name: integration name: Integration
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v5
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: package.json
cache: 'npm'
- run: npm ci - run: npm ci
- run: npm test - run: npm test
end-to-end: end-to-end:
name: end-to-end name: End-to-End
runs-on: ubuntu-latest runs-on: ubuntu-latest
# do not run from forks, as forks dont have access to repository secrets # do not run from forks, as forks dont have access to repository secrets
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login if: github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v5
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: package.json
cache: 'npm'
- run: npm ci - run: npm ci
- run: npm run build - run: npm run build
- uses: ./ # Uses the action in the root directory - uses: ./ # Uses the action in the root directory
@@ -54,28 +54,3 @@ jobs:
with: with:
route: GET /installation/repositories route: GET /installation/repositories
- run: echo '${{ steps.get-repository.outputs.data }}' - run: echo '${{ steps.get-repository.outputs.data }}'
end-to-end-proxy:
name: end-to-end with unreachable proxy
runs-on: ubuntu-latest
# do not run from forks, as forks dont have access to repository secrets
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: package.json
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: ./ # Uses the action in the root directory
continue-on-error: true
id: test
env:
NODE_USE_ENV_PROXY: "1"
https_proxy: http://127.0.0.1:9
with:
app-id: ${{ vars.TEST_APP_ID }}
private-key: ${{ secrets.TEST_APP_PRIVATE_KEY }}
- name: Assert action failed through unreachable proxy
run: test "${{ steps.test.outcome }}" = "failure"

View File

@@ -13,30 +13,21 @@ concurrency:
permissions: permissions:
contents: write contents: write
pull-requests: write
jobs: jobs:
update-permission-inputs: update-permission-inputs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
COMMIT_MESSAGE: 'feat: update permission inputs'
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v5
- uses: actions/setup-node@v6 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: package.json
cache: 'npm'
- name: Install dependencies - name: Install dependencies
run: npm ci run: npm ci
- name: Run permission inputs update script - name: Run permission inputs update script
run: node scripts/update-permission-inputs.js run: node scripts/update-permission-inputs.js
- name: Commit changes - name: Commit changes
id: auto-commit uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 # v5.2.0
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
with: with:
commit_message: ${{ env.COMMIT_MESSAGE }} commit_message: 'feat: update permission inputs'
- name: Update PR title
if: github.event_name == 'pull_request' && steps.auto-commit.outputs.changes_detected == 'true'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit ${{ github.event.pull_request.number }} --title "${{ env.COMMIT_MESSAGE }}"

View File

@@ -9,8 +9,8 @@ GitHub Action for creating a GitHub App installation access token.
In order to use this action, you need to: In order to use this action, you need to:
1. [Register new GitHub App](https://docs.github.com/apps/creating-github-apps/setting-up-a-github-app/creating-a-github-app). 1. [Register new GitHub App](https://docs.github.com/apps/creating-github-apps/setting-up-a-github-app/creating-a-github-app).
2. [Store the App's Client ID in your repository environment variables](https://docs.github.com/actions/how-tos/write-workflows/choose-what-workflows-do/use-variables#defining-configuration-variables-for-multiple-workflows) (example: `GITHUB_APP_CLIENT_ID`). 2. [Store the App's ID or Client ID in your repository environment variables](https://docs.github.com/actions/learn-github-actions/variables#defining-configuration-variables-for-multiple-workflows) (example: `APP_ID`).
3. [Store the App's private key in your repository secrets](https://docs.github.com/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets?tool=webui#creating-secrets-for-a-repository) (example: `GITHUB_APP_PRIVATE_KEY`). 3. [Store the App's private key in your repository secrets](https://docs.github.com/actions/security-guides/encrypted-secrets?tool=webui#creating-encrypted-secrets-for-a-repository) (example: `PRIVATE_KEY`).
> [!IMPORTANT] > [!IMPORTANT]
> An installation access token expires after 1 hour. Please [see this comment](https://github.com/actions/create-github-app-token/issues/121#issuecomment-2043214796) for alternative approaches if you have long-running processes. > An installation access token expires after 1 hour. Please [see this comment](https://github.com/actions/create-github-app-token/issues/121#issuecomment-2043214796) for alternative approaches if you have long-running processes.
@@ -31,8 +31,8 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
- uses: ./actions/staging-tests - uses: ./actions/staging-tests
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
@@ -51,15 +51,15 @@ jobs:
id: app-token id: app-token
with: with:
# required # required
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
- uses: actions/checkout@v6 - uses: actions/checkout@v5
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
ref: ${{ github.head_ref }} ref: ${{ github.head_ref }}
# Make sure the value of GITHUB_TOKEN will not be persisted in repo's config # Make sure the value of GITHUB_TOKEN will not be persisted in repo's config
persist-credentials: false persist-credentials: false
- uses: creyD/prettier_action@v6 - uses: creyD/prettier_action@v4.3
with: with:
github_token: ${{ steps.app-token.outputs.token }} github_token: ${{ steps.app-token.outputs.token }}
``` ```
@@ -77,8 +77,8 @@ jobs:
id: app-token id: app-token
with: with:
# required # required
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
- name: Get GitHub App User ID - name: Get GitHub App User ID
id: get-user-id id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
@@ -102,8 +102,8 @@ jobs:
id: app-token id: app-token
with: with:
# required # required
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
- name: Get GitHub App User ID - name: Get GitHub App User ID
id: get-user-id id: get-user-id
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
@@ -138,10 +138,10 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }} owner: ${{ github.repository_owner }}
- uses: peter-evans/create-or-update-comment@v4 - uses: peter-evans/create-or-update-comment@v3
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
@@ -160,13 +160,13 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }} owner: ${{ github.repository_owner }}
repositories: | repositories: |
repo1 repo1
repo2 repo2
- uses: peter-evans/create-or-update-comment@v4 - uses: peter-evans/create-or-update-comment@v3
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
@@ -185,10 +185,10 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
owner: another-owner owner: another-owner
- uses: peter-evans/create-or-update-comment@v4 - uses: peter-evans/create-or-update-comment@v3
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
@@ -210,11 +210,11 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ github.repository_owner }} owner: ${{ github.repository_owner }}
permission-issues: write permission-issues: write
- uses: peter-evans/create-or-update-comment@v4 - uses: peter-evans/create-or-update-comment@v3
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
issue-number: ${{ github.event.issue.number }} issue-number: ${{ github.event.issue.number }}
@@ -252,8 +252,8 @@ jobs:
- uses: actions/create-github-app-token@v3 - uses: actions/create-github-app-token@v3
id: app-token id: app-token
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} private-key: ${{ secrets.PRIVATE_KEY }}
owner: ${{ matrix.owners-and-repos.owner }} owner: ${{ matrix.owners-and-repos.owner }}
repositories: ${{ join(matrix.owners-and-repos.repos) }} repositories: ${{ join(matrix.owners-and-repos.repos) }}
- uses: octokit/request-action@v2.x - uses: octokit/request-action@v2.x
@@ -281,7 +281,7 @@ jobs:
id: create_token id: create_token
uses: actions/create-github-app-token@v3 uses: actions/create-github-app-token@v3
with: with:
client-id: ${{ vars.GHES_APP_CLIENT_ID }} app-id: ${{ vars.GHES_APP_ID }}
private-key: ${{ secrets.GHES_APP_PRIVATE_KEY }} private-key: ${{ secrets.GHES_APP_PRIVATE_KEY }}
owner: ${{ vars.GHES_INSTALLATION_ORG }} owner: ${{ vars.GHES_INSTALLATION_ORG }}
github-api-url: ${{ vars.GITHUB_API_URL }} github-api-url: ${{ vars.GITHUB_API_URL }}
@@ -296,32 +296,11 @@ jobs:
GITHUB_TOKEN: ${{ steps.create_token.outputs.token }} GITHUB_TOKEN: ${{ steps.create_token.outputs.token }}
``` ```
### Proxy support
This action relies on Node.js native proxy support.
If you set `HTTP_PROXY` or `HTTPS_PROXY`, also set `NODE_USE_ENV_PROXY: "1"` on the action step so Node.js honors those variables. If you need proxy bypass rules, set `NO_PROXY` alongside them.
```yaml
- uses: actions/create-github-app-token@v3
id: app-token
env:
HTTPS_PROXY: http://proxy.example.com:8080
NO_PROXY: github.example.com
NODE_USE_ENV_PROXY: "1"
with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
```
## Inputs ## Inputs
### `client-id` or `app-id` ### `app-id`
**Required:** GitHub App Client ID. **Required:** GitHub App ID.
> [!NOTE]
> The legacy `app-id` input is also accepted, but `client-id` is recommended.
### `private-key` ### `private-key`
@@ -334,14 +313,14 @@ steps:
- name: Decode the GitHub App Private Key - name: Decode the GitHub App Private Key
id: decode id: decode
run: | run: |
private_key=$(echo "${{ secrets.GITHUB_APP_PRIVATE_KEY }}" | base64 -d | awk 'BEGIN {ORS="\\n"} {print}' | head -c -2) &> /dev/null private_key=$(echo "${{ secrets.PRIVATE_KEY }}" | base64 -d | awk 'BEGIN {ORS="\\n"} {print}' | head -c -2) &> /dev/null
echo "::add-mask::$private_key" echo "::add-mask::$private_key"
echo "private-key=$private_key" >> "$GITHUB_OUTPUT" echo "private-key=$private_key" >> "$GITHUB_OUTPUT"
- name: Generate GitHub App Token - name: Generate GitHub App Token
id: app-token id: app-token
uses: actions/create-github-app-token@v3 uses: actions/create-github-app-token@v3
with: with:
client-id: ${{ vars.GITHUB_APP_CLIENT_ID }} app-id: ${{ vars.APP_ID }}
private-key: ${{ steps.decode.outputs.private-key }} private-key: ${{ steps.decode.outputs.private-key }}
``` ```

View File

@@ -5,13 +5,9 @@ branding:
icon: "lock" icon: "lock"
color: "gray-dark" color: "gray-dark"
inputs: inputs:
client-id:
description: "GitHub App Client ID"
required: false
app-id: app-id:
description: "GitHub App ID" description: "GitHub App ID"
required: false required: true
deprecationMessage: "Use 'client-id' instead."
private-key: private-key:
description: "GitHub App private key" description: "GitHub App private key"
required: true required: true
@@ -35,28 +31,18 @@ inputs:
description: "The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts. Can be set to 'read' or 'write'."
permission-administration: permission-administration:
description: "The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation. Can be set to 'read' or 'write'."
permission-artifact-metadata:
description: "The level of permission to grant the access token to create and retrieve build artifact metadata records. Can be set to 'read' or 'write'."
permission-attestations:
description: "The level of permission to create and retrieve the access token for repository attestations. Can be set to 'read' or 'write'."
permission-checks: permission-checks:
description: "The level of permission to grant the access token for checks on code. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for checks on code. Can be set to 'read' or 'write'."
permission-codespaces: permission-codespaces:
description: "The level of permission to grant the access token to create, edit, delete, and list Codespaces. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token to create, edit, delete, and list Codespaces. Can be set to 'read' or 'write'."
permission-contents: permission-contents:
description: "The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges. Can be set to 'read' or 'write'."
permission-custom-properties-for-organizations:
description: "The level of permission to grant the access token to view and edit custom properties for an organization, when allowed by the property. Can be set to 'read' or 'write'."
permission-dependabot-secrets: permission-dependabot-secrets:
description: "The level of permission to grant the access token to manage Dependabot secrets. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token to manage Dependabot secrets. Can be set to 'read' or 'write'."
permission-deployments: permission-deployments:
description: "The level of permission to grant the access token for deployments and deployment statuses. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for deployments and deployment statuses. Can be set to 'read' or 'write'."
permission-discussions:
description: "The level of permission to grant the access token for discussions and related comments and labels. Can be set to 'read' or 'write'."
permission-email-addresses: permission-email-addresses:
description: "The level of permission to grant the access token to manage the email addresses belonging to a user. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token to manage the email addresses belonging to a user. Can be set to 'read' or 'write'."
permission-enterprise-custom-properties-for-organizations:
description: "The level of permission to grant the access token for organization custom properties management at the enterprise level. Can be set to 'read', 'write', or 'admin'."
permission-environments: permission-environments:
description: "The level of permission to grant the access token for managing repository environments. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for managing repository environments. Can be set to 'read' or 'write'."
permission-followers: permission-followers:
@@ -71,8 +57,6 @@ inputs:
description: "The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones. Can be set to 'read' or 'write'."
permission-members: permission-members:
description: "The level of permission to grant the access token for organization teams and members. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for organization teams and members. Can be set to 'read' or 'write'."
permission-merge-queues:
description: "The level of permission to grant the access token to manage the merge queues for a repository. Can be set to 'read' or 'write'."
permission-metadata: permission-metadata:
description: "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata. Can be set to 'read' or 'write'."
permission-organization-administration: permission-organization-administration:
@@ -84,7 +68,7 @@ inputs:
permission-organization-custom-org-roles: permission-organization-custom-org-roles:
description: "The level of permission to grant the access token for custom organization roles management. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for custom organization roles management. Can be set to 'read' or 'write'."
permission-organization-custom-properties: permission-organization-custom-properties:
description: "The level of permission to grant the access token for repository custom properties management at the organization level. Can be set to 'read', 'write', or 'admin'." description: "The level of permission to grant the access token for custom property management. Can be set to 'read', 'write', or 'admin'."
permission-organization-custom-roles: permission-organization-custom-roles:
description: "The level of permission to grant the access token for custom repository roles management. Can be set to 'read' or 'write'." description: "The level of permission to grant the access token for custom repository roles management. Can be set to 'read' or 'write'."
permission-organization-events: permission-organization-events:

24137
dist/main.cjs vendored

File diff suppressed because one or more lines are too long

23371
dist/post.cjs vendored

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@ import pRetry from "p-retry";
// @ts-check // @ts-check
/** /**
* @param {string} clientId * @param {string} appId
* @param {string} privateKey * @param {string} privateKey
* @param {string} owner * @param {string} owner
* @param {string[]} repositories * @param {string[]} repositories
@@ -13,7 +13,7 @@ import pRetry from "p-retry";
* @param {boolean} skipTokenRevoke * @param {boolean} skipTokenRevoke
*/ */
export async function main( export async function main(
clientId, appId,
privateKey, privateKey,
owner, owner,
repositories, repositories,
@@ -70,7 +70,7 @@ export async function main(
} }
const auth = createAppAuth({ const auth = createAppAuth({
appId: clientId, appId,
privateKey, privateKey,
request, request,
}); });
@@ -89,12 +89,12 @@ export async function main(
permissions permissions
), ),
{ {
shouldRetry: ({ error }) => error.status >= 500, shouldRetry: (error) => error.status >= 500,
onFailedAttempt: (context) => { onFailedAttempt: (error) => {
core.info( core.info(
`Failed to create token for "${parsedRepositoryNames.join( `Failed to create token for "${parsedRepositoryNames.join(
"," ","
)}" (attempt ${context.attemptNumber}): ${context.error.message}` )}" (attempt ${error.attemptNumber}): ${error.message}`
); );
}, },
retries: 3, retries: 3,
@@ -105,9 +105,9 @@ export async function main(
({ authentication, installationId, appSlug } = await pRetry( ({ authentication, installationId, appSlug } = await pRetry(
() => getTokenFromOwner(request, auth, parsedOwner, permissions), () => getTokenFromOwner(request, auth, parsedOwner, permissions),
{ {
onFailedAttempt: (context) => { onFailedAttempt: (error) => {
core.info( core.info(
`Failed to create token for "${parsedOwner}" (attempt ${context.attemptNumber}): ${context.error.message}` `Failed to create token for "${parsedOwner}" (attempt ${error.attemptNumber}): ${error.message}`
); );
}, },
retries: 3, retries: 3,

View File

@@ -1,34 +1,9 @@
import * as core from "@actions/core"; import core from "@actions/core";
import { request } from "@octokit/request"; import { request } from "@octokit/request";
// Get the GitHub API URL from the action input and remove any trailing slash // Get the GitHub API URL from the action input and remove any trailing slash
const baseUrl = core.getInput("github-api-url").replace(/\/$/, ""); const baseUrl = core.getInput("github-api-url").replace(/\/$/, "");
const proxyEnvironmentKeys = [
"https_proxy",
"HTTPS_PROXY",
"http_proxy",
"HTTP_PROXY",
];
function proxyEnvironmentConfigured() {
return proxyEnvironmentKeys.some((key) => process.env[key]);
}
function nativeProxySupportEnabled() {
return process.env.NODE_USE_ENV_PROXY === "1";
}
export function ensureNativeProxySupport() {
if (!proxyEnvironmentConfigured() || nativeProxySupportEnabled()) {
return;
}
throw new Error(
"A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.",
);
}
// Configure the default settings for GitHub API requests // Configure the default settings for GitHub API requests
export default request.defaults({ export default request.defaults({
headers: { "user-agent": "actions/create-github-app-token" }, headers: { "user-agent": "actions/create-github-app-token" },

55
main.js
View File

@@ -1,11 +1,11 @@
// @ts-check // @ts-check
import * as core from "@actions/core"; import core from "@actions/core";
import { createAppAuth } from "@octokit/auth-app"; import { createAppAuth } from "@octokit/auth-app";
import { getPermissionsFromInputs } from "./lib/get-permissions-from-inputs.js"; import { getPermissionsFromInputs } from "./lib/get-permissions-from-inputs.js";
import { main } from "./lib/main.js"; import { main } from "./lib/main.js";
import request, { ensureNativeProxySupport } from "./lib/request.js"; import request from "./lib/request.js";
if (!process.env.GITHUB_REPOSITORY) { if (!process.env.GITHUB_REPOSITORY) {
throw new Error("GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'"); throw new Error("GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'");
@@ -15,40 +15,31 @@ if (!process.env.GITHUB_REPOSITORY_OWNER) {
throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'"); throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'");
} }
async function run() { const appId = core.getInput("app-id");
ensureNativeProxySupport(); const privateKey = core.getInput("private-key");
const owner = core.getInput("owner");
const repositories = core
.getInput("repositories")
.split(/[\n,]+/)
.map((s) => s.trim())
.filter((x) => x !== "");
const clientId = core.getInput("client-id") || core.getInput("app-id"); const skipTokenRevoke = core.getBooleanInput("skip-token-revoke");
if (!clientId) {
throw new Error("Either 'client-id' or 'app-id' input must be set");
}
const privateKey = core.getInput("private-key");
const owner = core.getInput("owner");
const repositories = core
.getInput("repositories")
.split(/[\n,]+/)
.map((s) => s.trim())
.filter((x) => x !== "");
const skipTokenRevoke = core.getBooleanInput("skip-token-revoke"); const permissions = getPermissionsFromInputs(process.env);
const permissions = getPermissionsFromInputs(process.env);
return main(
clientId,
privateKey,
owner,
repositories,
permissions,
core,
createAppAuth,
request,
skipTokenRevoke,
);
}
// Export promise for testing // Export promise for testing
export default run().catch((error) => { export default main(
appId,
privateKey,
owner,
repositories,
permissions,
core,
createAppAuth,
request,
skipTokenRevoke,
).catch((error) => {
/* c8 ignore next 3 */ /* c8 ignore next 3 */
console.error(error); console.error(error);
core.setFailed(error.message); core.setFailed(error.message);

3208
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,32 +2,35 @@
"name": "create-github-app-token", "name": "create-github-app-token",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "3.1.0", "version": "3.0.0-beta.2",
"description": "GitHub Action for creating a GitHub App Installation Access Token", "description": "GitHub Action for creating a GitHub App Installation Access Token",
"engines": { "engines": {
"node": ">=24.4.0" "node": ">=24.4.0"
}, },
"packageManager": "npm@10.9.4",
"scripts": { "scripts": {
"build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --packages=bundle", "build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --packages=bundle",
"test": "c8 --100 node --test tests/index.js", "test": "c8 --100 ava tests/index.js",
"coverage": "c8 report --reporter html", "coverage": "c8 report --reporter html",
"postcoverage": "open-cli coverage/index.html" "postcoverage": "open-cli coverage/index.html"
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^3.0.0", "@actions/core": "^1.11.1",
"@octokit/auth-app": "^8.2.0", "@octokit/auth-app": "^7.2.1",
"@octokit/request": "^10.0.8", "@octokit/request": "^9.2.2",
"p-retry": "^8.0.0" "p-retry": "^6.2.1"
}, },
"devDependencies": { "devDependencies": {
"@octokit/openapi": "^22.0.0", "@octokit/openapi": "^19.1.0",
"c8": "^11.0.0", "@sinonjs/fake-timers": "^14.0.0",
"esbuild": "^0.27.4", "ava": "^6.4.1",
"open-cli": "^9.0.0", "c8": "^10.1.3",
"undici": "^7.24.6", "dotenv": "^17.2.1",
"yaml": "^2.8.3" "esbuild": "^0.25.8",
"execa": "^9.6.0",
"open-cli": "^8.0.0",
"undici": "^7.13.0",
"yaml": "^2.8.1"
}, },
"release": { "release": {
"branches": [ "branches": [
@@ -43,7 +46,6 @@
"@semantic-release/release-notes-generator", "@semantic-release/release-notes-generator",
"@semantic-release/github", "@semantic-release/github",
"@semantic-release/npm", "@semantic-release/npm",
"semantic-release-plugin-github-breaking-version-tag",
[ [
"@semantic-release/git", "@semantic-release/git",
{ {

12
post.js
View File

@@ -1,17 +1,11 @@
// @ts-check // @ts-check
import * as core from "@actions/core"; import core from "@actions/core";
import { post } from "./lib/post.js"; import { post } from "./lib/post.js";
import request, { ensureNativeProxySupport } from "./lib/request.js"; import request from "./lib/request.js";
async function run() { post(core, request).catch((error) => {
ensureNativeProxySupport();
return post(core, request);
}
run().catch((error) => {
/* c8 ignore next 3 */ /* c8 ignore next 3 */
console.error(error); console.error(error);
core.setFailed(error.message); core.setFailed(error.message);

View File

@@ -19,22 +19,6 @@
"write" "write"
] ]
}, },
"artifact_metadata": {
"type": "string",
"description": "The level of permission to grant the access token to create and retrieve build artifact metadata records.",
"enum": [
"read",
"write"
]
},
"attestations": {
"type": "string",
"description": "The level of permission to create and retrieve the access token for repository attestations.",
"enum": [
"read",
"write"
]
},
"checks": { "checks": {
"type": "string", "type": "string",
"description": "The level of permission to grant the access token for checks on code.", "description": "The level of permission to grant the access token for checks on code.",
@@ -75,14 +59,6 @@
"write" "write"
] ]
}, },
"discussions": {
"type": "string",
"description": "The level of permission to grant the access token for discussions and related comments and labels.",
"enum": [
"read",
"write"
]
},
"environments": { "environments": {
"type": "string", "type": "string",
"description": "The level of permission to grant the access token for managing repository environments.", "description": "The level of permission to grant the access token for managing repository environments.",
@@ -99,14 +75,6 @@
"write" "write"
] ]
}, },
"merge_queues": {
"type": "string",
"description": "The level of permission to grant the access token to manage the merge queues for a repository.",
"enum": [
"read",
"write"
]
},
"metadata": { "metadata": {
"type": "string", "type": "string",
"description": "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata.", "description": "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata.",
@@ -219,14 +187,6 @@
"write" "write"
] ]
}, },
"custom_properties_for_organizations": {
"type": "string",
"description": "The level of permission to grant the access token to view and edit custom properties for an organization, when allowed by the property.",
"enum": [
"read",
"write"
]
},
"members": { "members": {
"type": "string", "type": "string",
"description": "The level of permission to grant the access token for organization teams and members.", "description": "The level of permission to grant the access token for organization teams and members.",
@@ -261,7 +221,7 @@
}, },
"organization_custom_properties": { "organization_custom_properties": {
"type": "string", "type": "string",
"description": "The level of permission to grant the access token for repository custom properties management at the organization level.", "description": "The level of permission to grant the access token for custom property management.",
"enum": [ "enum": [
"read", "read",
"write", "write",
@@ -424,15 +384,6 @@
"read", "read",
"write" "write"
] ]
},
"enterprise_custom_properties_for_organizations": {
"type": "string",
"description": "The level of permission to grant the access token for organization custom properties management at the enterprise level.",
"enum": [
"read",
"write",
"admin"
]
} }
}, },
"example": { "example": {

View File

@@ -2,14 +2,14 @@
Add one test file per scenario. You can run them in isolation with: Add one test file per scenario. You can run them in isolation with:
``` ```bash
node tests/post-token-set.test.js node tests/post-token-set.test.js
``` ```
All tests are run together in [tests/index.js](index.js), which can be executed with Node's built-in test runner All tests are run together in [tests/index.js](index.js), which can be executed with ava
``` ```
node --test tests/index.js npx ava tests/index.js
``` ```
or with npm or with npm
@@ -20,17 +20,11 @@ npm test
## How the tests work ## How the tests work
The output from the tests is captured into a snapshot ([tests/index.js.snapshot](index.js.snapshot)). It includes all requests sent by our scripts to verify it's working correctly and to prevent regressions. The output from the tests is captured into a snapshot ([tests/snapshots/index.js.md](snapshots/index.js.md)). It includes all requests sent by our scripts to verify it's working correctly and to prevent regressions.
To update snapshots after an intentional change:
```
node --test --test-update-snapshots tests/index.js
```
## How to add a new test ## How to add a new test
We have tests both for the `main.js` and `post.js` scripts. We have tests both for the `main.js` and `post.js` scripts.
- If you do not expect an error, take [main-token-permissions-set.test.js](main-token-permissions-set.test.js) as a starting point. - If you do not expect an error, take [main-token-permissions-set.test.js](tests/main-token-permissions-set.test.js) as a starting point.
- If your test has an expected error, take [main-missing-client-and-app-id.test.js](main-missing-client-and-app-id.test.js) as a starting point. - If your test has an expected error, take [main-missing-app-id.test.js](tests/main-missing-app-id.test.js) as a starting point.

View File

@@ -1,23 +1,15 @@
import { readdirSync } from "node:fs"; import { readdirSync } from "node:fs";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { snapshot, test } from "node:test"; import test from "ava";
import { execa } from "execa";
const execFileAsync = promisify(execFile);
// Serialize strings as-is so multiline output is human-readable in snapshots
snapshot.setDefaultSnapshotSerializers([
(value) => (typeof value === "string" ? value : undefined),
]);
// Get all files in tests directory // Get all files in tests directory
const files = readdirSync("tests"); const files = readdirSync("tests");
// Files to ignore // Files to ignore
const ignore = ["index.js", "index.js.snapshot", "main.js", "README.md"]; const ignore = ["index.js", "main.js", "README.md", "snapshots"];
const testFiles = files.filter((file) => !ignore.includes(file)).sort(); const testFiles = files.filter((file) => !ignore.includes(file));
// Throw an error if there is a file that does not end with test.js in the tests directory // Throw an error if there is a file that does not end with test.js in the tests directory
for (const file of testFiles) { for (const file of testFiles) {
@@ -26,31 +18,12 @@ for (const file of testFiles) {
} }
test(file, async (t) => { test(file, async (t) => {
// Override Actions environment variables that change `core`s behavior // Override Actions environment variables that change `core`s behavior
const { const env = {
GITHUB_OUTPUT, GITHUB_OUTPUT: undefined,
GITHUB_STATE, GITHUB_STATE: undefined,
HTTP_PROXY, };
HTTPS_PROXY, const { stderr, stdout } = await execa("node", [`tests/${file}`], { env });
http_proxy, t.snapshot(stderr, "stderr");
https_proxy, t.snapshot(stdout, "stdout");
NO_PROXY,
no_proxy,
NODE_OPTIONS,
NODE_USE_ENV_PROXY,
...env
} = process.env;
const { stderr, stdout } = await execFileAsync("node", [`tests/${file}`], {
env,
});
const trimmedStderr = stderr.replace(/\r?\n$/, "");
const trimmedStdout = stdout.replace(/\r?\n$/, "");
await t.test("stderr", (t) => {
if (trimmedStderr) t.assert.snapshot(trimmedStderr);
else t.assert.strictEqual(trimmedStderr, "");
});
await t.test("stdout", (t) => {
if (trimmedStdout) t.assert.snapshot(trimmedStdout);
else t.assert.strictEqual(trimmedStdout, "");
});
}); });
} }

View File

@@ -1,320 +0,0 @@
exports[`action-deprecated-inputs.test.js > stdout 1`] = `
app-id — Use 'client-id' instead.
`;
exports[`main-app-id-fallback.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-client-id-precedence.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-custom-github-api-url.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/create-github-app-token
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /api/v3/repos/actions/create-github-app-token/installation
POST /api/v3/app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-missing-client-and-app-id.test.js > stderr 1`] = `
Either 'client-id' or 'app-id' input must be set
`;
exports[`main-missing-client-and-app-id.test.js > stdout 1`] = `
::error::Either 'client-id' or 'app-id' input must be set
`;
exports[`main-missing-owner.test.js > stderr 1`] = `
GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'
`;
exports[`main-missing-repository.test.js > stderr 1`] = `
GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'
`;
exports[`main-private-key-with-escaped-newlines.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-proxy-requires-native-support.test.js > stderr 1`] = `
A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.
`;
exports[`main-proxy-requires-native-support.test.js > stdout 1`] = `
::error::A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.
`;
exports[`main-repo-skew.test.js > stderr 1`] = `
'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued.
[@octokit/auth-app] GitHub API time and system time are different by 30 seconds. Retrying request with the difference accounted for.
`;
exports[`main-repo-skew.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/failed-repo
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/failed-repo/installation
GET /repos/actions/failed-repo/installation
POST /app/installations/123456/access_tokens
{"repositories":["failed-repo"]}
`;
exports[`main-token-get-owner-set-fail-response.test.js > stdout 1`] = `
Input 'repositories' is not set. Creating token for all repositories owned by smockle.
Failed to create token for "smockle" (attempt 1): GitHub API not available
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /users/smockle/installation
GET /users/smockle/installation
POST /app/installations/123456/access_tokens
null
`;
exports[`main-token-get-owner-set-repo-fail-response.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/failed-repo
Failed to create token for "failed-repo" (attempt 1): GitHub API not available
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/failed-repo/installation
GET /repos/actions/failed-repo/installation
POST /app/installations/123456/access_tokens
{"repositories":["failed-repo"]}
`;
exports[`main-token-get-owner-set-repo-set-to-many-newline.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/create-github-app-token
- actions/toolkit
- actions/checkout
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token","toolkit","checkout"]}
`;
exports[`main-token-get-owner-set-repo-set-to-many.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/create-github-app-token
- actions/toolkit
- actions/checkout
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token","toolkit","checkout"]}
`;
exports[`main-token-get-owner-set-repo-set-to-one.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
- actions/create-github-app-token
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-token-get-owner-set-repo-unset.test.js > stdout 1`] = `
Input 'repositories' is not set. Creating token for all repositories owned by actions.
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /users/actions/installation
POST /app/installations/123456/access_tokens
null
`;
exports[`main-token-get-owner-unset-repo-set.test.js > stdout 1`] = `
No 'owner' input provided. Using default owner 'actions' to create token for the following repositories:
- actions/create-github-app-token
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-token-get-owner-unset-repo-unset.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"]}
`;
exports[`main-token-permissions-set.test.js > stdout 1`] = `
Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::set-output name=installation-id::123456
::set-output name=app-slug::github-actions
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a
::save-state name=expiresAt::2016-07-11T22:14:10Z
--- REQUESTS ---
GET /repos/actions/create-github-app-token/installation
POST /app/installations/123456/access_tokens
{"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}
`;
exports[`post-proxy-requires-native-support.test.js > stderr 1`] = `
A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.
`;
exports[`post-proxy-requires-native-support.test.js > stdout 1`] = `
::error::A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.
`;
exports[`post-revoke-token-fail-response.test.js > stdout 1`] = `
::warning::Token revocation failed:
`;
exports[`post-token-expired.test.js > stdout 1`] = `
Token expired, skipping token revocation
`;
exports[`post-token-set.test.js > stdout 1`] = `
Token revoked
`;
exports[`post-token-skipped.test.js > stdout 1`] = `
Token revocation was skipped
`;
exports[`post-token-unset.test.js > stdout 1`] = `
Token is not set
`;

View File

@@ -1,11 +0,0 @@
import { DEFAULT_ENV, test } from "./main.js";
// Verify `main` falls back to `app-id` when `client-id` is not set
await test(
() => {},
{
...DEFAULT_ENV,
"INPUT_CLIENT-ID": "",
"INPUT_APP-ID": "123456",
}
);

View File

@@ -1,11 +0,0 @@
import { DEFAULT_ENV, test } from "./main.js";
// Verify `client-id` takes precedence when both `client-id` and `app-id` are set
await test(
() => {},
{
...DEFAULT_ENV,
"INPUT_CLIENT-ID": "Iv1.0123456789abcdef",
"INPUT_APP-ID": "123456",
}
);

View File

@@ -1,20 +0,0 @@
import { DEFAULT_ENV } from "./main.js";
for (const [key, value] of Object.entries({
...DEFAULT_ENV,
"INPUT_CLIENT-ID": "",
"INPUT_APP-ID": "",
})) {
process.env[key] = value;
}
// Log only the error message, not the full stack trace, because the stack
// trace contains environment-specific paths and ANSI codes that differ
// between local and CI environments.
const _error = console.error;
console.error = (err) => _error(err?.message ?? err);
// Verify `main` exits with an error when neither `client-id` nor `app-id` is set.
const { default: promise } = await import("../main.js");
await promise;
process.exitCode = 0;

View File

@@ -1,14 +0,0 @@
process.env.GITHUB_REPOSITORY = "actions/create-github-app-token";
process.env.GITHUB_REPOSITORY_OWNER = "actions";
process.env.HTTPS_PROXY = "http://127.0.0.1:3128";
const originalConsoleError = console.error;
console.error = (...args) => {
originalConsoleError(
...args.map((arg) => (arg instanceof Error ? arg.message : arg)),
);
};
await import("../main.js");
await new Promise((resolve) => setImmediate(resolve));
process.exitCode = 0;

View File

@@ -1,7 +1,7 @@
import { mock } from "node:test";
import { test } from "./main.js"; import { test } from "./main.js";
import { install } from "@sinonjs/fake-timers";
// Verify `main` retry when the clock has drifted. // Verify `main` retry when the clock has drifted.
await test((mockPool) => { await test((mockPool) => {
process.env.INPUT_OWNER = "actions"; process.env.INPUT_OWNER = "actions";
@@ -11,7 +11,7 @@ await test((mockPool) => {
const mockInstallationId = "123456"; const mockInstallationId = "123456";
const mockAppSlug = "github-actions"; const mockAppSlug = "github-actions";
mock.timers.enable({ apis: ["Date"], now: 0 }); install({ now: 0, toFake: ["Date"] });
mockPool mockPool
.intercept({ .intercept({
@@ -59,6 +59,4 @@ await test((mockPool) => {
}; };
}) })
.times(2); .times(2);
}).finally(() => {
mock.timers.reset();
}); });

View File

@@ -9,7 +9,7 @@ export const DEFAULT_ENV = {
// https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs // https://docs.github.com/actions/creating-actions/metadata-syntax-for-github-actions#example-specifying-inputs
"INPUT_GITHUB-API-URL": "https://api.github.com", "INPUT_GITHUB-API-URL": "https://api.github.com",
"INPUT_SKIP-TOKEN-REVOKE": "false", "INPUT_SKIP-TOKEN-REVOKE": "false",
"INPUT_CLIENT-ID": "Iv1.0123456789abcdef", "INPUT_APP-ID": "123456",
// This key is invalidated. Its from https://github.com/octokit/auth-app.js/issues/465#issuecomment-1564998327. // This key is invalidated. Its from https://github.com/octokit/auth-app.js/issues/465#issuecomment-1564998327.
"INPUT_PRIVATE-KEY": `-----BEGIN RSA PRIVATE KEY----- "INPUT_PRIVATE-KEY": `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA280nfuUM9w00Ib9E2rvZJ6Qu3Ua3IqR34ZlK53vn/Iobn2EL MIIEowIBAAKCAQEA280nfuUM9w00Ib9E2rvZJ6Qu3Ua3IqR34ZlK53vn/Iobn2EL

View File

@@ -1,13 +0,0 @@
process.env["INPUT_GITHUB-API-URL"] = "https://api.github.com";
process.env.HTTPS_PROXY = "http://127.0.0.1:3128";
const originalConsoleError = console.error;
console.error = (...args) => {
originalConsoleError(
...args.map((arg) => (arg instanceof Error ? arg.message : arg)),
);
};
await import("../post.js");
await new Promise((resolve) => setImmediate(resolve));
process.exitCode = 0;

384
tests/snapshots/index.js.md Normal file
View File

@@ -0,0 +1,384 @@
# Snapshot report for `tests/index.js`
The actual snapshot is saved in `index.js.snap`.
Generated by [AVA](https://avajs.dev).
## action-deprecated-inputs.test.js
> stderr
''
> stdout
''
## main-custom-github-api-url.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/create-github-app-token␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /api/v3/repos/actions/create-github-app-token/installation␊
POST /api/v3/app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"]}`
## main-missing-owner.test.js
> stderr
'GITHUB_REPOSITORY_OWNER missing, must be set to \'<owner>\''
> stdout
''
## main-missing-repository.test.js
> stderr
'GITHUB_REPOSITORY missing, must be set to \'<owner>/<repo>\''
> stdout
''
## main-private-key-with-escaped-newlines.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"]}`
## main-repo-skew.test.js
> stderr
`'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued.␊
[@octokit/auth-app] GitHub API time and system time are different by 30 seconds. Retrying request with the difference accounted for.`
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/failed-repo␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/failed-repo/installation␊
GET /repos/actions/failed-repo/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["failed-repo"]}`
## main-token-get-owner-set-fail-response.test.js
> stderr
''
> stdout
`Input 'repositories' is not set. Creating token for all repositories owned by smockle.␊
Failed to create token for "smockle" (attempt 1): GitHub API not available␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /users/smockle/installation␊
GET /users/smockle/installation␊
POST /app/installations/123456/access_tokens␊
null`
## main-token-get-owner-set-repo-fail-response.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/failed-repo␊
Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/failed-repo/installation␊
GET /repos/actions/failed-repo/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["failed-repo"]}`
## main-token-get-owner-set-repo-set-to-many-newline.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/create-github-app-token␊
- actions/toolkit␊
- actions/checkout␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token","toolkit","checkout"]}`
## main-token-get-owner-set-repo-set-to-many.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/create-github-app-token␊
- actions/toolkit␊
- actions/checkout␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token","toolkit","checkout"]}`
## main-token-get-owner-set-repo-set-to-one.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:␊
- actions/create-github-app-token␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"]}`
## main-token-get-owner-set-repo-unset.test.js
> stderr
''
> stdout
`Input 'repositories' is not set. Creating token for all repositories owned by actions.␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /users/actions/installation␊
POST /app/installations/123456/access_tokens␊
null`
## main-token-get-owner-unset-repo-set.test.js
> stderr
''
> stdout
`No 'owner' input provided. Using default owner 'actions' to create token for the following repositories:␊
- actions/create-github-app-token␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"]}`
## main-token-get-owner-unset-repo-unset.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"]}`
## main-token-permissions-set.test.js
> stderr
''
> stdout
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (actions/create-github-app-token).␊
::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::set-output name=installation-id::123456␊
::set-output name=app-slug::github-actions␊
::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊
::save-state name=expiresAt::2016-07-11T22:14:10Z␊
--- REQUESTS ---␊
GET /repos/actions/create-github-app-token/installation␊
POST /app/installations/123456/access_tokens␊
{"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}`
## post-revoke-token-fail-response.test.js
> stderr
''
> stdout
'::warning::Token revocation failed: '
## post-token-expired.test.js
> stderr
''
> stdout
'Token expired, skipping token revocation'
## post-token-set.test.js
> stderr
''
> stdout
'Token revoked'
## post-token-skipped.test.js
> stderr
''
> stdout
'Token revocation was skipped'
## post-token-unset.test.js
> stderr
''
> stdout
'Token is not set'

Binary file not shown.