Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Remove the need for an ADMIN_GITHUB_TOKEN #557

Merged
merged 11 commits into from
Mar 4, 2024
4 changes: 3 additions & 1 deletion .github/workflows/prep-self-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ on:
jobs:
prep_release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
Expand All @@ -37,7 +39,7 @@ jobs:
id: prep-release
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
version_spec: ${{ github.event.inputs.version_spec }}
post_version_spec: ${{ github.event.inputs.post_version_spec }}
target: jupyter-server/jupyter_releaser
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/publish-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ on:
jobs:
publish_changelog:
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/checkout@v4
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Install Dependencies
shell: bash
run: |
pip install -e .

- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Publish changelog
id: publish-changelog
uses: jupyter-server/jupyter_releaser/.github/actions/publish-changelog@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
target: ${{ github.event.inputs.target }}
branch: ${{ github.event.inputs.branch }}

Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/publish-self-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ jobs:
runs-on: ubuntu-latest
environment: release
permissions:
# This is useful if you want to use PyPI trusted publisher
# and NPM provenance
id-token: write
steps:
- uses: actions/checkout@v4
Expand All @@ -27,11 +25,16 @@ jobs:
shell: bash
run: |
pip install -e .
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Populate Release
id: populate-release
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
target: jupyter-server/jupyter_releaser
branch: ${{ github.event.inputs.branch }}
release_url: ${{ github.event.inputs.release_url }}
Expand All @@ -43,7 +46,7 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
target: ${{ github.event.inputs.target }}
release_url: ${{ steps.populate-release.outputs.release_url }}

Expand Down
7 changes: 7 additions & 0 deletions docs/source/background/theory.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ This project should help maintainers reduce toil and save time in the release pr
- Dry run publish on CI
- Revert to Dev version after release (optional)

## Security

We strive to use the most secure release practices possible, reflected in the `Checklist for Adoption`
and the example workflows.
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.
In addition, there is an automatic check for whether the user who triggered the action is an admin.

## Action Details

Detailed workflows are available to draft a changelog, draft a release, publish a release, and check a release.
Expand Down
47 changes: 30 additions & 17 deletions docs/source/how_to_guides/convert_repo_from_repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,30 @@ See checklist below for details:

## Checklist for Adoption

- [ ] 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
account that has admin access to the repository. The token itself will
need "public_repo", and "repo:status" permissions. Save the token as
`ADMIN_GITHUB_TOKEN`
in the [repository secrets](https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository). We need this
access token to allow for branch protection rules, which block the pushing
of commits when using the `GITHUB_TOKEN`, even when run from an admin user
account.
- [ ] 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).

- [ ] Set up PyPI:
- Disable the web hook
- Enable Repository permissions > Contents > Read and write
- Select "Only on this account"
- Click "Create GitHub App"
- Browse to the App Settings
- Select "Install App" and install on all repositories
- Under "General" click "Generate a private key"
- Store the `APP_ID` and the private key in a secure location (Jupyter Vault if using a Jupyter Org)

<details><summary>Using PyPI token (legacy way)</summary>
- [ ] 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we advice to allow that environment only on protected branches?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, updated


- 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`.
_Note_ For security reasons, it is recommended that you scope the access
to a single repository. Additionally, this token should belong to a
machine account and not a user account.
- [ ] Configure [Rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets) for the repository

</details>
- Set up branch protection but only disable force pushes.
blink1073 marked this conversation as resolved.
Show resolved Hide resolved
- Remove global tag protection.
- Add a branch Ruleset for all branches
- Allow the GitHub App to bypass protections
- Set up Pull Request and Required Checks
- Add a tags Ruleset for all tags
- Allow the GitHub App to bypass protections

- [ ] Set up PyPI:

<details><summary>Using PyPI trusted publisher (modern way)</summary>

Expand All @@ -45,10 +50,18 @@ See checklist below for details:

</details>

<details><summary>Using PyPI token (legacy way)</summary>

- 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`.
_Note_ For security reasons, it is recommended that you scope the access
to a single repository. Additionally, this token should belong to a
machine account and not a user account.

</details>

- [ ] If needed, add access token for [npm](https://docs.npmjs.com/creating-and-viewing-access-tokens), saved as `NPM_TOKEN`. Again this should
be created using a machine account that only has publish access.
- [ ] Ensure that only trusted users with 2FA have admin access to the
repository, since they will be able to trigger releases.
- [ ] Ensure that only trusted users with 2FA have admin access to the repository, since they will be able to trigger releases.
- [ ] Switch to Markdown Changelog
- We recommend [MyST](https://myst-parser.readthedocs.io/en/latest/?badge=latest), especially if some of your docs are in reStructuredText.
- Can use `pandoc -s changelog.rst -o changelog.md` and some hand edits as needed.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/how_to_guides/maintain_fork.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

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

- Make sure your workflow is up to date by checking the "Fetch Upstream" dropdown on the main page of your fork.
Expand Down
52 changes: 35 additions & 17 deletions example-workflows/full-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ on:
post_version_spec:
description: "Post Version Specifier"
required: false
# silent:
# description: "Set a placeholder in the changelog and don't publish the release."
# required: false
# type: boolean
silent:
description: "Set a placeholder in the changelog and don't publish the release."
required: false
type: boolean
since:
description: "Use PRs with activity since this date or git reference"
required: false
Expand All @@ -27,51 +27,69 @@ on:
description: "Comma separated list of steps to skip during Populate Release"
required: false
jobs:
full_release:
prep_release:
runs-on: ubuntu-latest
permissions:
# This is useful if you want to use PyPI trusted publisher
# and NPM provenance
id-token: write
contents: write
steps:
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Prep Release
id: prep-release
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
version_spec: ${{ github.event.inputs.version_spec }}
silent: ${{ github.event.inputs.silent }}
post_version_spec: ${{ github.event.inputs.post_version_spec }}
target: ${{ github.event.inputs.target }}
branch: ${{ github.event.inputs.branch }}
# silent: ${{ github.event.inputs.silent }}
since: ${{ github.event.inputs.since }}
since_last_stable: ${{ github.event.inputs.since_last_stable }}

publish_release:
needs: [prep_release]
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Populate Release
id: populate-release
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
target: ${{ github.event.inputs.target }}
branch: ${{ github.event.inputs.branch }}
release_url: ${{ steps.prep-release.outputs.release_url }}
release_url: ${{ github.event.inputs.release_url }}
steps_to_skip: ${{ github.event.inputs.steps_to_skip }}

- name: Finalize Release
id: finalize-release
env:
# The following are needed if you use legacy PyPI set up
# PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
# PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }}
# TWINE_USERNAME: __token__
Comment on lines -63 to -66
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this for now as we don't remove legacy PyPI publication yet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having it in the docs is enough, new projects should be using Trusted Publishing.

NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
target: ${{ github.event.inputs.target }}
release_url: ${{ steps.populate-release.outputs.release_url }}

- name: "** Next Step **"
if: ${{ success() }}
run: |
echo "Verify the final release"
echo ${{ steps.finalize-release.outputs.release_url }}

- name: "** Failure Message **"
if: ${{ failure() }}
run: |
echo "Failed to Publish the Draft Release Url:"
echo ${{ steps.populate-release.outputs.release_url }}
15 changes: 9 additions & 6 deletions example-workflows/prep-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ on:
post_version_spec:
description: "Post Version Specifier"
required: false
# silent:
# description: "Set a placeholder in the changelog and don't publish the release."
# required: false
# type: boolean
silent:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc this was left commented so that the input does not show up in the UI as this is more of an advanced feature (discussed in #526)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay fair, I'll comment it out

description: "Set a placeholder in the changelog and don't publish the release."
required: false
type: boolean
since:
description: "Use PRs with activity since this date or git reference"
required: false
Expand All @@ -26,18 +26,21 @@ on:
jobs:
prep_release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Prep Release
id: prep-release
uses: jupyter-server/jupyter_releaser/.github/actions/prep-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
version_spec: ${{ github.event.inputs.version_spec }}
silent: ${{ github.event.inputs.silent }}
post_version_spec: ${{ github.event.inputs.post_version_spec }}
target: ${{ github.event.inputs.target }}
branch: ${{ github.event.inputs.branch }}
# silent: ${{ github.event.inputs.silent }}
since: ${{ github.event.inputs.since }}
since_last_stable: ${{ github.event.inputs.since_last_stable }}

Expand Down
10 changes: 9 additions & 1 deletion example-workflows/publish-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ on:
jobs:
publish_changelog:
runs-on: ubuntu-latest
environment: release
steps:
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Publish changelog
id: publish-changelog
uses: jupyter-server/jupyter_releaser/.github/actions/publish-changelog@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
branch: ${{ github.event.inputs.branch }}

- name: "** Next Step **"
Expand Down
17 changes: 9 additions & 8 deletions example-workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,34 @@ on:
jobs:
publish_release:
runs-on: ubuntu-latest
environment: release
permissions:
# This is useful if you want to use PyPI trusted publisher
# and NPM provenance
id-token: write
steps:
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Populate Release
id: populate-release
uses: jupyter-server/jupyter_releaser/.github/actions/populate-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
branch: ${{ github.event.inputs.branch }}
release_url: ${{ github.event.inputs.release_url }}
steps_to_skip: ${{ github.event.inputs.steps_to_skip }}

- name: Finalize Release
id: finalize-release
env:
# The following are needed if you use legacy PyPI set up
# PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
# PYPI_TOKEN_MAP: ${{ secrets.PYPI_TOKEN_MAP }}
# TWINE_USERNAME: __token__
Comment on lines -37 to -40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment

NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
uses: jupyter-server/jupyter_releaser/.github/actions/finalize-release@v2
with:
token: ${{ secrets.ADMIN_GITHUB_TOKEN }}
token: ${{ steps.app-token.outputs.token }}
release_url: ${{ steps.populate-release.outputs.release_url }}

- name: "** Next Step **"
Expand Down
Loading