Skip to content

Commit a349a20

Browse files
authored
Remove the need for an ADMIN_GITHUB_TOKEN (#557)
1 parent 58a343c commit a349a20

File tree

10 files changed

+115
-50
lines changed

10 files changed

+115
-50
lines changed

.github/workflows/prep-self-release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ on:
2626
jobs:
2727
prep_release:
2828
runs-on: ubuntu-latest
29+
permissions:
30+
contents: write
2931
steps:
3032
- uses: actions/checkout@v4
3133
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
@@ -37,7 +39,7 @@ jobs:
3739
id: prep-release
3840
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
3941
with:
40-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
42+
token: ${{ secrets.GITHUB_TOKEN }}
4143
version_spec: ${{ github.event.inputs.version_spec }}
4244
post_version_spec: ${{ github.event.inputs.post_version_spec }}
4345
target: jupyter-server/jupyter_releaser

.github/workflows/publish-changelog.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,27 @@ on:
1212
jobs:
1313
publish_changelog:
1414
runs-on: ubuntu-latest
15+
environment: release
1516
steps:
1617
- uses: actions/checkout@v4
1718
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
19+
1820
- name: Install Dependencies
1921
shell: bash
2022
run: |
2123
pip install -e .
24+
25+
- uses: actions/create-github-app-token@v1
26+
id: app-token
27+
with:
28+
app-id: ${{ vars.APP_ID }}
29+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
30+
2231
- name: Publish changelog
2332
id: publish-changelog
2433
uses: jupyter-server/jupyter_releaser/.github/actions/publish-changelog@v2
2534
with:
26-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
35+
token: ${{ steps.app-token.outputs.token }}
2736
target: ${{ github.event.inputs.target }}
2837
branch: ${{ github.event.inputs.branch }}
2938

.github/workflows/publish-self-release.yml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ jobs:
1717
runs-on: ubuntu-latest
1818
environment: release
1919
permissions:
20-
# This is useful if you want to use PyPI trusted publisher
21-
# and NPM provenance
2220
id-token: write
2321
steps:
2422
- uses: actions/checkout@v4
@@ -27,11 +25,16 @@ jobs:
2725
shell: bash
2826
run: |
2927
pip install -e .
28+
- uses: actions/create-github-app-token@v1
29+
id: app-token
30+
with:
31+
app-id: ${{ vars.APP_ID }}
32+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
3033
- name: Populate Release
3134
id: populate-release
3235
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
3336
with:
34-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
37+
token: ${{ steps.app-token.outputs.token }}
3538
target: jupyter-server/jupyter_releaser
3639
branch: ${{ github.event.inputs.branch }}
3740
release_url: ${{ github.event.inputs.release_url }}
@@ -43,7 +46,7 @@ jobs:
4346
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
4447
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
4548
with:
46-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
49+
token: ${{ steps.app-token.outputs.token }}
4750
target: ${{ github.event.inputs.target }}
4851
release_url: ${{ steps.populate-release.outputs.release_url }}
4952

docs/source/background/theory.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ This project should help maintainers reduce toil and save time in the release pr
1313
- Dry run publish on CI
1414
- Revert to Dev version after release (optional)
1515

16+
## Security
17+
18+
We strive to use the most secure release practices possible, reflected in the `Checklist for Adoption`
19+
and the example workflows.
20+
This includes using PyPI Trusted Publishing, using GitHub Environments, encouraging the use of Rulesets and GitHub Apps with limited bypass capability, and provenance data for npm.
21+
In addition, there is an automatic check for whether the user who triggered the action is an admin.
22+
1623
## Action Details
1724

1825
Detailed workflows are available to draft a changelog, draft a release, publish a release, and check a release.

docs/source/how_to_guides/convert_repo_from_repo.md

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,32 @@ See checklist below for details:
1616

1717
## Checklist for Adoption
1818

19-
- [ ] Add a GitHub [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token), preferably from a "machine user" GitHub
20-
account that has admin access to the repository. The token itself will
21-
need "public_repo", and "repo:status" permissions. Save the token as
22-
`ADMIN_GITHUB_TOKEN`
23-
in the [repository secrets](https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository). We need this
24-
access token to allow for branch protection rules, which block the pushing
25-
of commits when using the `GITHUB_TOKEN`, even when run from an admin user
26-
account.
19+
- [ ] Set up a [GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps#github-apps-that-act-on-their-own-behalf) on your organization (or personal account for a personal project).
20+
21+
- Disable the web hook
22+
- Enable Repository permissions > Contents > Read and write
23+
- Select "Only on this account"
24+
- Click "Create GitHub App"
25+
- Browse to the App Settings
26+
- Select "Install App" and install on all repositories
27+
- Under "General" click "Generate a private key"
28+
- Store the `APP_ID` and the private key in a secure location (Jupyter Vault if using a Jupyter Org)
29+
30+
- [ ] Create a "release" [environment](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment) on your repository and add an `APP_ID` Environment Variable and `APP_PRIVATE_KEY` secret.
31+
The environment should be enabled for ["Protected branches only"](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-branches-and-tags).
32+
33+
- [ ] Configure [Rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets) for the repository
34+
35+
- Set up branch protection (with default rules) on publication branches
36+
- Remove global tag protection.
37+
- Add a branch Ruleset for all branches
38+
- Allow the GitHub App to bypass protections
39+
- Set up Pull Request and Required Checks
40+
- Add a tags Ruleset for all tags
41+
- Allow the GitHub App to bypass protections
2742

2843
- [ ] Set up PyPI:
2944

30-
<details><summary>Using PyPI token (legacy way)</summary>
31-
32-
- Add access token for the [PyPI registry](https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#saving-credentials-on-github) stored as `PYPI_TOKEN`.
33-
_Note_ For security reasons, it is recommended that you scope the access
34-
to a single repository. Additionally, this token should belong to a
35-
machine account and not a user account.
36-
37-
</details>
38-
3945
<details><summary>Using PyPI trusted publisher (modern way)</summary>
4046

4147
- Set up your PyPI project by [adding a trusted publisher](https://docs.pypi.org/trusted-publishers/adding-a-publisher/)
@@ -45,10 +51,18 @@ See checklist below for details:
4551

4652
</details>
4753

54+
<details><summary>Using PyPI token (legacy way)</summary>
55+
56+
- Add access token for the [PyPI registry](https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/#saving-credentials-on-github) stored as `PYPI_TOKEN`.
57+
_Note_ For security reasons, it is recommended that you scope the access
58+
to a single repository. Additionally, this token should belong to a
59+
machine account and not a user account.
60+
61+
</details>
62+
4863
- [ ] If needed, add access token for [npm](https://docs.npmjs.com/creating-and-viewing-access-tokens), saved as `NPM_TOKEN`. Again this should
4964
be created using a machine account that only has publish access.
50-
- [ ] Ensure that only trusted users with 2FA have admin access to the
51-
repository, since they will be able to trigger releases.
65+
- [ ] Ensure that only trusted users with 2FA have admin access to the repository, since they will be able to trigger releases.
5266
- [ ] Switch to Markdown Changelog
5367
- We recommend [MyST](https://myst-parser.readthedocs.io/en/latest/?badge=latest), especially if some of your docs are in reStructuredText.
5468
- Can use `pandoc -s changelog.rst -o changelog.md` and some hand edits as needed.

docs/source/how_to_guides/maintain_fork.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## How to keep fork of Jupyter Releaser up to date
44

5-
- The manual workflow files target the `@v1` actions in the source repository, which means that as long as
5+
- The manual workflow files target the `@v2` actions in the source repository, which means that as long as
66
the workflow files themselves are up to date, you will always be running the most up to date actions.
77

88
- Make sure your workflow is up to date by checking the "Fetch Upstream" dropdown on the main page of your fork.

example-workflows/full-release.yml

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,51 +27,69 @@ on:
2727
description: "Comma separated list of steps to skip during Populate Release"
2828
required: false
2929
jobs:
30-
full_release:
30+
prep_release:
3131
runs-on: ubuntu-latest
3232
permissions:
33-
# This is useful if you want to use PyPI trusted publisher
34-
# and NPM provenance
35-
id-token: write
33+
contents: write
3634
steps:
3735
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
3836

3937
- name: Prep Release
4038
id: prep-release
4139
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
4240
with:
43-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
41+
token: ${{ secrets.GITHUB_TOKEN }}
4442
version_spec: ${{ github.event.inputs.version_spec }}
43+
# silent: ${{ github.event.inputs.silent }}
4544
post_version_spec: ${{ github.event.inputs.post_version_spec }}
45+
target: ${{ github.event.inputs.target }}
4646
branch: ${{ github.event.inputs.branch }}
47-
# silent: ${{ github.event.inputs.silent }}
4847
since: ${{ github.event.inputs.since }}
4948
since_last_stable: ${{ github.event.inputs.since_last_stable }}
5049

50+
publish_release:
51+
needs: [prep_release]
52+
runs-on: ubuntu-latest
53+
environment: release
54+
permissions:
55+
id-token: write
56+
steps:
57+
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
58+
59+
- uses: actions/create-github-app-token@v1
60+
id: app-token
61+
with:
62+
app-id: ${{ vars.APP_ID }}
63+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
64+
5165
- name: Populate Release
5266
id: populate-release
5367
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
5468
with:
55-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
69+
token: ${{ steps.app-token.outputs.token }}
70+
target: ${{ github.event.inputs.target }}
5671
branch: ${{ github.event.inputs.branch }}
57-
release_url: ${{ steps.prep-release.outputs.release_url }}
72+
release_url: ${{ github.event.inputs.release_url }}
5873
steps_to_skip: ${{ github.event.inputs.steps_to_skip }}
5974

6075
- name: Finalize Release
6176
id: finalize-release
6277
env:
63-
# The following are needed if you use legacy PyPI set up
64-
# PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
65-
# PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }}
66-
# TWINE_USERNAME: __token__
6778
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
6879
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
6980
with:
70-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
81+
token: ${{ steps.app-token.outputs.token }}
82+
target: ${{ github.event.inputs.target }}
7183
release_url: ${{ steps.populate-release.outputs.release_url }}
7284

7385
- name: "** Next Step **"
7486
if: ${{ success() }}
7587
run: |
7688
echo "Verify the final release"
7789
echo ${{ steps.finalize-release.outputs.release_url }}
90+
91+
- name: "** Failure Message **"
92+
if: ${{ failure() }}
93+
run: |
94+
echo "Failed to Publish the Draft Release Url:"
95+
echo ${{ steps.populate-release.outputs.release_url }}

example-workflows/prep-release.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,21 @@ on:
2626
jobs:
2727
prep_release:
2828
runs-on: ubuntu-latest
29+
permissions:
30+
contents: write
2931
steps:
3032
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
3133

3234
- name: Prep Release
3335
id: prep-release
3436
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
3537
with:
36-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
38+
token: ${{ secrets.GITHUB_TOKEN }}
3739
version_spec: ${{ github.event.inputs.version_spec }}
40+
# silent: ${{ github.event.inputs.silent }}
3841
post_version_spec: ${{ github.event.inputs.post_version_spec }}
42+
target: ${{ github.event.inputs.target }}
3943
branch: ${{ github.event.inputs.branch }}
40-
# silent: ${{ github.event.inputs.silent }}
4144
since: ${{ github.event.inputs.since }}
4245
since_last_stable: ${{ github.event.inputs.since_last_stable }}
4346

example-workflows/publish-changelog.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@ on:
1212
jobs:
1313
publish_changelog:
1414
runs-on: ubuntu-latest
15+
environment: release
1516
steps:
1617
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
18+
19+
- uses: actions/create-github-app-token@v1
20+
id: app-token
21+
with:
22+
app-id: ${{ vars.APP_ID }}
23+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
24+
1725
- name: Publish changelog
1826
id: publish-changelog
1927
uses: jupyter-server/jupyter_releaser/.github/actions/publish-changelog@v2
2028
with:
21-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
29+
token: ${{ steps.app-token.outputs.token }}
2230
branch: ${{ github.event.inputs.branch }}
2331

2432
- name: "** Next Step **"

example-workflows/publish-release.yml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,34 @@ on:
1515
jobs:
1616
publish_release:
1717
runs-on: ubuntu-latest
18+
environment: release
1819
permissions:
19-
# This is useful if you want to use PyPI trusted publisher
20-
# and NPM provenance
2120
id-token: write
2221
steps:
2322
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
2423

24+
- uses: actions/create-github-app-token@v1
25+
id: app-token
26+
with:
27+
app-id: ${{ vars.APP_ID }}
28+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
29+
2530
- name: Populate Release
2631
id: populate-release
2732
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
2833
with:
29-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
34+
token: ${{ steps.app-token.outputs.token }}
3035
branch: ${{ github.event.inputs.branch }}
3136
release_url: ${{ github.event.inputs.release_url }}
3237
steps_to_skip: ${{ github.event.inputs.steps_to_skip }}
3338

3439
- name: Finalize Release
3540
id: finalize-release
3641
env:
37-
# The following are needed if you use legacy PyPI set up
38-
# PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
39-
# PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }}
40-
# TWINE_USERNAME: __token__
4142
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
4243
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
4344
with:
44-
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
45+
token: ${{ steps.app-token.outputs.token }}
4546
release_url: ${{ steps.populate-release.outputs.release_url }}
4647

4748
- name: "** Next Step **"

0 commit comments

Comments
 (0)