This is a quick follow-up to #59. I was mid-review when it merged and
noticed one instance of `skip_token_revoke` in the README that didn't
get changed to `skip-token-revoke`. The PR merged just before I pushed a
commit to fix it.
Fixes#57
This PR implements the 3-step plan proposed by @gr2m in
https://github.com/actions/create-github-app-token/issues/57#issuecomment-1751272252:
> 1. Support both input types
> 2. Log a deprecation warning for the old notation
> 3. Add a test for deprecations
Although this PR supports both input formats simultaneously, I opted
_not_ to document the old format in the updated README. That’s a
decision I’m happy to revisit, if y’all would prefer to have
documentation for both the old and new formats.
Part of https://github.com/actions/create-github-app-token/issues/43
This PR adds tests for
[`main.js`](https://github.com/actions/create-github-app-token/blob/main/lib/main.js),
similar to [the tests that already exist for
`post.js`](https://github.com/actions/create-github-app-token/tree/main/tests).
Specifically, it tests that:
- `main` exits with an error when `GITHUB_REPOSITORY` is missing.
- `main` exits with an error when `GITHUB_REPOSITORY_OWNER` is missing.
- `main` successfully obtains a token when…
- …the `owner` and `repositories` inputs are set (and the latter is a
single repo).
- …the `owner` and `repositories` inputs are set (and the latter is a
list of repos).
- …the `owner` input is set (to an org), but the `repositories` input
isn’t set.
- …the `owner` input is set (to a user), but the `repositories` input
isn’t set.
- …the `owner` input is not set, but the `repositories` input is set.
- …neither the `owner` nor `repositories` input is set.
❧
Architecturally, in order to keep individual tests concise, this PR adds
`tests/main.js`, which:
- sets commonly-used inputs, environment variables, and mocks, then
- calls a callback function that can edit the variables and add
additional mocks, then
- runs `main.js` itself.
The `tests/main-token-get-*.test.js` test files run `tests/main.js` with
various scenario-specific callback functions.
Fixes https://github.com/actions/create-github-app-token/issues/55
Currently, `actions/create-github-app-token` always/unconditionally
revokes the installation access token in a `post` step, at the
completion of the current job. This prevents tokens from being used in
other jobs.
This PR makes this behavior configurable:
- When the `skip-token-revoke` input is not specified (i.e. by default),
the token is revoked in a `post` step (i.e. the current behavior).
- When the `skip-token-revoke` input is set to a truthy value (e.g.
`"true"`[^1]), the token is not revoked in a `post` step.
This PR adds a test for the `skip-token-revoke: "true"` case.
This is configurable in other app token actions, e.g.
[tibdex/github-app-token](https://github.com/tibdex/github-app-token/blob/3eb77c7243b85c65e84acfa93fdbac02fb6bd532/README.md?plain=1#L46-L47)
and
[wow-actions/use-app-token](https://github.com/wow-actions/use-app-token/blob/cd772994fc762f99cf291f308797341327a49b0c/README.md?plain=1#L132).
[^1]: Note that `"false"` is also truthy: `Boolean("false")` is `true`.
If we think that’ll potentially confuse folks, I can require
`skip-token-revoke` to be set explicitly to `"true"`.
Follow up to #36. I just wanted to do some refactoring but turns out I
missed to pass the custom `request` instance to `createAppAuth`. It will
fallback to the default `request` which does not respect
`GITHUB_API_URL`
Check before trying to revoke the token, in case the token generation
failed. Otherwise the post step will throw an error.
---------
Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
With #13, this action is explicitly masking the token so we don't need to mention that we're relying on a specific format of GitHub tokens being masked by the runner.
The runner will automatically mask GitHub token formats it recognizes,
but sometimes a new pattern rolls out before the runner is updated to
recognize it.
- Group production and development dependency updates
- Configure dependency update commit prefixes to release on production
dependency updates
Dependabot commit messages before:
- `build(deps): bump semver from 7.5.1 to 7.5.4`
- `build(deps-dev): bump dotenv from 16.0.3 to 16.3.1`
Dependabot commit messages after:
- `fix(deps): bump semver from 7.5.1 to 7.5.4`
- `build(deps-dev): bump dotenv from 16.0.3 to 16.3.1` (no change to dev
dependencies)
- Run test on pull requests to the main branch instead of on every push
- Cancel in-progress workflows if a PR is updated (i.e., a new commit is
pushed) and the same workflows are triggered to run again
- Rename step ID from `demo` to `test`
---------
Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
Bumps [esbuild](https://github.com/evanw/esbuild) from 0.17.19 to
0.19.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/evanw/esbuild/releases">esbuild's
releases</a>.</em></p>
<blockquote>
<h2>v0.19.2</h2>
<ul>
<li>
<p>Update how CSS nesting is parsed again</p>
<p>CSS nesting syntax has been changed again, and esbuild has been
updated to match. Type selectors may now be used with CSS nesting:</p>
<pre lang="css"><code>.foo {
div {
color: red;
}
}
</code></pre>
<p>Previously this was disallowed in the CSS specification because it's
ambiguous whether an identifier is a declaration or a nested rule
starting with a type selector without requiring unbounded lookahead in
the parser. It has now been allowed because the CSS working group has
decided that requiring unbounded lookahead is acceptable after all.</p>
<p>Note that this change means esbuild no longer considers any existing
browser to support CSS nesting since none of the existing browsers
support this new syntax. CSS nesting will now always be transformed when
targeting a browser. This situation will change in the future as
browsers add support for this new syntax.</p>
</li>
<li>
<p>Fix a scope-related bug with <code>--drop-labels=</code> (<a
href="https://redirect.github.com/evanw/esbuild/issues/3311">#3311</a>)</p>
<p>The recently-released <code>--drop-labels=</code> feature previously
had a bug where esbuild's internal scope stack wasn't being restored
properly when a statement with a label was dropped. This could manifest
as a tree-shaking issue, although it's possible that this could have
also been causing other subtle problems too. The bug has been fixed in
this release.</p>
</li>
<li>
<p>Make renamed CSS names unique across entry points (<a
href="https://redirect.github.com/evanw/esbuild/issues/3295">#3295</a>)</p>
<p>Previously esbuild's generated names for local names in CSS were only
unique within a given entry point (or across all entry points when code
splitting was enabled). That meant that building multiple entry points
with esbuild could result in local names being renamed to the same
identifier even when those entry points were built simultaneously within
a single esbuild API call. This problem was especially likely to happen
with minification enabled. With this release, esbuild will now avoid
renaming local names from two separate entry points to the same name if
those entry points were built with a single esbuild API call, even when
code splitting is disabled.</p>
</li>
<li>
<p>Fix CSS ordering bug with <code>@layer</code> before
<code>@import</code></p>
<p>CSS lets you put <code>@layer</code> rules before
<code>@import</code> rules to define the order of layers in a
stylesheet. Previously esbuild's CSS bundler incorrectly ordered these
after the imported files because before the introduction of cascade
layers to CSS, imported files could be bundled by removing the
<code>@import</code> rules and then joining files together in the right
order. But with <code>@layer</code>, CSS files may now need to be split
apart into multiple pieces in the bundle. For example:</p>
<pre><code>/* Original code */
@layer start;
@import "data:text/css,@layer inner.start;";
@import "data:text/css,@layer inner.end;";
@layer end;
<p>/* Old output (with --bundle) */
<a href="https://github.com/layer"><code>@layer</code></a> inner.start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.end;
<a href="https://github.com/layer"><code>@layer</code></a> start;
<a href="https://github.com/layer"><code>@layer</code></a> end;</p>
<p>/* New output (with --bundle) */
<a href="https://github.com/layer"><code>@layer</code></a> start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.end;
<a href="https://github.com/layer"><code>@layer</code></a> end;
</code></pre></p>
</li>
<li>
<p>Unwrap nested duplicate <code>@media</code> rules (<a
href="https://redirect.github.com/evanw/esbuild/issues/3226">#3226</a>)</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/evanw/esbuild/blob/main/CHANGELOG.md">esbuild's
changelog</a>.</em></p>
<blockquote>
<h2>0.19.2</h2>
<ul>
<li>
<p>Update how CSS nesting is parsed again</p>
<p>CSS nesting syntax has been changed again, and esbuild has been
updated to match. Type selectors may now be used with CSS nesting:</p>
<pre lang="css"><code>.foo {
div {
color: red;
}
}
</code></pre>
<p>Previously this was disallowed in the CSS specification because it's
ambiguous whether an identifier is a declaration or a nested rule
starting with a type selector without requiring unbounded lookahead in
the parser. It has now been allowed because the CSS working group has
decided that requiring unbounded lookahead is acceptable after all.</p>
<p>Note that this change means esbuild no longer considers any existing
browser to support CSS nesting since none of the existing browsers
support this new syntax. CSS nesting will now always be transformed when
targeting a browser. This situation will change in the future as
browsers add support for this new syntax.</p>
</li>
<li>
<p>Fix a scope-related bug with <code>--drop-labels=</code> (<a
href="https://redirect.github.com/evanw/esbuild/issues/3311">#3311</a>)</p>
<p>The recently-released <code>--drop-labels=</code> feature previously
had a bug where esbuild's internal scope stack wasn't being restored
properly when a statement with a label was dropped. This could manifest
as a tree-shaking issue, although it's possible that this could have
also been causing other subtle problems too. The bug has been fixed in
this release.</p>
</li>
<li>
<p>Make renamed CSS names unique across entry points (<a
href="https://redirect.github.com/evanw/esbuild/issues/3295">#3295</a>)</p>
<p>Previously esbuild's generated names for local names in CSS were only
unique within a given entry point (or across all entry points when code
splitting was enabled). That meant that building multiple entry points
with esbuild could result in local names being renamed to the same
identifier even when those entry points were built simultaneously within
a single esbuild API call. This problem was especially likely to happen
with minification enabled. With this release, esbuild will now avoid
renaming local names from two separate entry points to the same name if
those entry points were built with a single esbuild API call, even when
code splitting is disabled.</p>
</li>
<li>
<p>Fix CSS ordering bug with <code>@layer</code> before
<code>@import</code></p>
<p>CSS lets you put <code>@layer</code> rules before
<code>@import</code> rules to define the order of layers in a
stylesheet. Previously esbuild's CSS bundler incorrectly ordered these
after the imported files because before the introduction of cascade
layers to CSS, imported files could be bundled by removing the
<code>@import</code> rules and then joining files together in the right
order. But with <code>@layer</code>, CSS files may now need to be split
apart into multiple pieces in the bundle. For example:</p>
<pre><code>/* Original code */
@layer start;
@import "data:text/css,@layer inner.start;";
@import "data:text/css,@layer inner.end;";
@layer end;
<p>/* Old output (with --bundle) */
<a href="https://github.com/layer"><code>@layer</code></a> inner.start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.end;
<a href="https://github.com/layer"><code>@layer</code></a> start;
<a href="https://github.com/layer"><code>@layer</code></a> end;</p>
<p>/* New output (with --bundle) */
<a href="https://github.com/layer"><code>@layer</code></a> start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.start;
<a href="https://github.com/layer"><code>@layer</code></a> inner.end;
<a href="https://github.com/layer"><code>@layer</code></a> end;
</code></pre></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/evanw/esbuild/commit/09a100124e9daef9e0be57d21cc7729c6f3516e7"><code>09a1001</code></a>
publish 0.19.2 to npm</li>
<li><a
href="https://github.com/evanw/esbuild/commit/4d9b764f11b8f52024c798f3e3361be9f575b1cc"><code>4d9b764</code></a>
fix <a
href="https://redirect.github.com/evanw/esbuild/issues/3311">#3311</a>:
pop scope after <code>--drop-labels=</code> runs</li>
<li><a
href="https://github.com/evanw/esbuild/commit/f2d23b294e41253062f6c49fd7e339dfb8019940"><code>f2d23b2</code></a>
fix some typos</li>
<li><a
href="https://github.com/evanw/esbuild/commit/e76780c041b15fbf5d273861af2a95707f1621f1"><code>e76780c</code></a>
css: further changes to css nesting syntax</li>
<li><a
href="https://github.com/evanw/esbuild/commit/71f4a5aff3c943d2f44c606337a9a4d5ef530e31"><code>71f4a5a</code></a>
update compat-table (note: css nesting changed)</li>
<li><a
href="https://github.com/evanw/esbuild/commit/eb667c35bd1c32b3ea2fc5f56326665298131b3a"><code>eb667c3</code></a>
css: try to merge adjacent <code>@layer</code> rules together</li>
<li><a
href="https://github.com/evanw/esbuild/commit/f7596931bb79ab8708dd630aa729d49bc68bbbbd"><code>f759693</code></a>
css: fix ordering with <code>@layer</code> before
<code>@import</code></li>
<li><a
href="https://github.com/evanw/esbuild/commit/c73f0f8fc9185f7b2335363a2f8b98e29077a327"><code>c73f0f8</code></a>
css: extract wrapping logic to a helper function</li>
<li><a
href="https://github.com/evanw/esbuild/commit/a05a2f9c7a91dbe32202f4e963c8aca9ec24481d"><code>a05a2f9</code></a>
css: make source index on compile results optional</li>
<li><a
href="https://github.com/evanw/esbuild/commit/bb16fb7a92f07136d4b5b6a07132367e6533dc59"><code>bb16fb7</code></a>
css: parser separates layers pre/post <code>@import</code></li>
<li>Additional commits viewable in <a
href="https://github.com/evanw/esbuild/compare/v0.17.19...v0.19.2">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Configures Dependabot version updates, which enables Dependabot to open
pull requests automatically to keep dependencies up-to-date when new
versions are available.
- Update title
- Remove blockquote formatting from description to improve accessibility
- Capitalize "app" in "GitHub App" for consistency
- Add missing periods in unordered list
- Use new highlight syntax for note
> GitHub Action for creating a GitHub App Installation Access Token
GitHub Action for creating a GitHub App installation access token.
## Usage
@@ -10,7 +10,7 @@ In order to use this action, you need to:
2. [Store the App's 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/security-guides/encrypted-secrets?tool=webui#creating-encrypted-secrets-for-a-repository) (example: `PRIVATE_KEY`)
### Minimal usage
### Create a token for the current repository
```yaml
on:[issues]
@@ -19,11 +19,11 @@ jobs:
hello-world:
runs-on:ubuntu-latest
steps:
- uses:gr2m/github-app-token-action@v1
- uses:actions/create-github-app-token@v1
id:app-token
with:
app_id:${{ vars.APP_ID }}
private_key:${{ secrets.PRIVATE_KEY }}
app-id:${{ vars.APP_ID }}
private-key:${{ secrets.PRIVATE_KEY }}
- uses:peter-evans/create-or-update-comment@v3
with:
token:${{ steps.app-token.outputs.token }}
@@ -31,24 +31,6 @@ jobs:
body:"Hello, World!"
```
### Limit the app's permissions and access to repositories
```yaml
on:[issues]
jobs:
with-scoped-token:
runs-on:ubuntu-latest
steps:
- uses:gr2m/github-app-token-action@v1
id:app-token
with:
# required
app_id:${{ vars.APP_ID }}
private_key:${{ secrets.PRIVATE_KEY }}
# do something with the token
```
### Use app token with `actions/checkout`
```yaml
@@ -58,12 +40,12 @@ jobs:
auto-format:
runs-on:ubuntu-latest
steps:
- uses:gr2m/github-app-token-action@v1
- uses:actions/create-github-app-token@v1
id:app-token
with:
# required
app_id:${{ vars.APP_ID }}
private_key:${{ secrets.PRIVATE_KEY }}
app-id:${{ vars.APP_ID }}
private-key:${{ secrets.PRIVATE_KEY }}
- uses:actions/checkout@v3
with:
token:${{ steps.app-token.outputs.token }}
@@ -75,33 +57,115 @@ jobs:
github_token:${{ steps.app-token.outputs.token }}
```
### Create a token for all repositories in the current owner's installation
```yaml
on:[workflow_dispatch]
jobs:
hello-world:
runs-on:ubuntu-latest
steps:
- uses:actions/create-github-app-token@v1
id:app-token
with:
app-id:${{ vars.APP_ID }}
private-key:${{ secrets.PRIVATE_KEY }}
owner:${{ github.repository_owner }}
- uses:peter-evans/create-or-update-comment@v3
with:
token:${{ steps.app-token.outputs.token }}
issue-number:${{ github.event.issue.number }}
body:"Hello, World!"
```
### Create a token for multiple repositories in the current owner's installation
```yaml
on:[issues]
jobs:
hello-world:
runs-on:ubuntu-latest
steps:
- uses:actions/create-github-app-token@v1
id:app-token
with:
app-id:${{ vars.APP_ID }}
private-key:${{ secrets.PRIVATE_KEY }}
owner:${{ github.repository_owner }}
repositories:"repo1,repo2"
- uses:peter-evans/create-or-update-comment@v3
with:
token:${{ steps.app-token.outputs.token }}
issue-number:${{ github.event.issue.number }}
body:"Hello, World!"
```
### Create a token for all repositories in another owner's installation
```yaml
on:[issues]
jobs:
hello-world:
runs-on:ubuntu-latest
steps:
- uses:actions/create-github-app-token@v1
id:app-token
with:
app-id:${{ vars.APP_ID }}
private-key:${{ secrets.PRIVATE_KEY }}
owner:another-owner
- uses:peter-evans/create-or-update-comment@v3
with:
token:${{ steps.app-token.outputs.token }}
issue-number:${{ github.event.issue.number }}
body:"Hello, World!"
```
## Inputs
### `app_id`
### `app-id`
**Required:** GitHub app ID.
**Required:** GitHub App ID.
### `private_key`
### `private-key`
**Required:** GitHub app private key.
**Required:** GitHub App private key.
### `owner`
**Optional:** GitHub App installation owner. If empty, defaults to the current repository owner.
### `repositories`
**Optional:** Comma-separated list of repositories to grant access to.
> [!NOTE]
> If `owner` is set and `repositories` is empty, access will be scoped to all repositories in the provided repository owner's installation. If `owner` and `repositories` are empty, access will be scoped to only the current repository.
### `skip-token-revoke`
**Optional:** If truthy, the token will not be revoked when the current job is complete.
## Outputs
### `token`
GitHub installation access token.
GitHub App installation access token.
## How it works
The action creates an installation access token using [the `POST /app/installations/{installation_id}/access_tokens` endpoint](https://docs.github.com/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app). By default,
1. The token is scoped to the current repository
2. The token inherits all the installation's permissions
3. The token is set as output `token` which can be used in subsequent steps
4.The token is revoked in the `post` step of the action, which means it cannot be passed to another job.
5. The token is masked, it cannot be logged accidentally. That is not a feature by the action, but by the GitHub Actions runner itself, due to the specific format of GitHub tokens.
1. The token is scoped to the current repository or `repositories` if set.
2. The token inherits all the installation's permissions.
3. The token is set as output `token` which can be used in subsequent steps.
4.Unless the `skip-token-revoke` input is set to a truthy value, the token is revoked in the `post` step of the action, which means it cannot be passed to another job.
5. The token is masked, it cannot be logged accidentally.
> **Note**
> [!NOTE]
> Installation permissions can differ from the app's permissions they belong to. Installation permissions are set when an app is installed on an account. When the app adds more permissions after the installation, an account administrator will have to approve the new permissions before they are set on the installation.
// The 'app_id' input was previously required, but it and 'app-id' are both optional now, until the former is removed. Still, we want to ensure that at least one of them is set.
thrownewError("Input required and not supplied: app-id");
// The 'private_key' input was previously required, but it and 'private-key' are both optional now, until the former is removed. Still, we want to ensure that at least one of them is set.
thrownewError("Input required and not supplied: private-key");
// Intentionally omitting the `authorization` header, since JWT creation is not idempotent.
},
})
.reply(
200,
{id:mockInstallationId},
{headers:{"content-type":"application/json"}}
);
// Mock installation access token request
constmockInstallationAccessToken=
"ghs_16C7e42F292c6912E7710c838347Ae178B4a";// This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.