From 37a91b5179adc2cbf78ea6a773364db3669785b8 Mon Sep 17 00:00:00 2001 From: Carlo van Overbeek Date: Mon, 29 Dec 2025 17:15:57 +0100 Subject: [PATCH] automate releasing with default github token --- docs/extra_guides.md | 6 ++ docs/walkthrough.md | 29 ++++---- .../.github/workflows/publish-docs.yaml | 41 ----------- .../.github/workflows/release-please.yaml | 26 ------- .../.github/workflows/release.yaml | 72 +++++++++++++++++-- 5 files changed, 87 insertions(+), 87 deletions(-) delete mode 100644 {{ cookiecutter.project_slug }}/.github/workflows/publish-docs.yaml delete mode 100644 {{ cookiecutter.project_slug }}/.github/workflows/release-please.yaml diff --git a/docs/extra_guides.md b/docs/extra_guides.md index 0922d5a..b425b73 100644 --- a/docs/extra_guides.md +++ b/docs/extra_guides.md @@ -29,6 +29,12 @@ Protecting your repository from insider threats is far harder, but this might he - Set some "Required reviewers" under "Environments" -> "Deployment protection rules". - Cumbersome to implement, but effective: org/repo admin access only for non-personal accounts which require 4-eyes approval for assuming. +Protecting your repository is important, even more so when it's hooked up to CI/CD. +GitHub security is a subject by itself. +Do not just rely on the checklist above. +Think about your own situation, and implement the checks and balances you think are necessary. +As always, the internet can help you with thinking. + ## Executable apps > You may need to flush uv's cache after implementing the code below before the commands will work. diff --git a/docs/walkthrough.md b/docs/walkthrough.md index 91c9c9f..c9beda4 100644 --- a/docs/walkthrough.md +++ b/docs/walkthrough.md @@ -155,17 +155,12 @@ Others might particularly like automated publishing to other documentation hosti Instructions: -- Navigate to `https://github.com/settings/personal-access-tokens`. -- Generate a new token; - it should have access "Read and Write" on "Contents" and "Pull requests" on ONLY the repository you are working with now, - this will also automatically grant access "Read-only" on "Metadata". -- Go to `https://github.com///settings/environments/new` and create an environment called `release-please`. -- Set "Deployment branches and tags" to only allow branch `main` to use the new environment. -- Set `RELEASE_PLEASE_TOKEN` as an environment secret with the token you just generated. +- Navigate to `https://github.com///settings/actions`. +- Check "Allow GitHub Actions to create and approve pull requests" and save the changes. - Get back to the command-line in your local clone. - Execute `git commit --allow-empty -m "feat: release initial version"` and `git push`. - Navigate to `https://github.com///actions`; - see that the "Quality Assurance CI" and "Release Please" workflows succeed. + see that the "Quality Assurance CI" and "Release Orchestration" workflows succeed. - Go to `https://github.com///pull/1`; see that Release Please created a pull request for you. @@ -185,15 +180,18 @@ Release Please expects commits to adhere to [Conventional Commits](https://www.c This is a good idea anyway, so that should be a reasonable demand. (When merging commits into the main branch with pull requests, it is probably easiest to make the PR title adhere to Conventional Commits and to 'squash merge'.) -Sadly, Release Please does require a dedicated GitHub token to operate, because actions triggered from pull requests are too limited for this template when operating with the default GitHub token. -The token is something quite sensitive to manage, because it breaks those (security) limits, but worth that effort. -Be especially careful on new workflows that create toxic permission combinations which allow pull requests from strangers to escalate privileges. -See the [extra guides](extra_guides.md#github-security-enhancements) on some more tips on securing your repository. +Sadly, GitHub does not allow the results from GitHub Actions with the default token and triggered by a pull request to trigger further GitHub Actions. +This makes the `release.yaml` a bit overcrowded. +The easiest alternative is feeding the Release Please Action a custom PAT. +Otherwise, you have to write a whole CI/CD system around your repository. +Pick your poison... + +If you want the release automation to do more than what this template provides, you will have to write it in the `release.yaml` as well or go the other routes. ## Publishing to PyPI and GitHub Pages - Navigate to `https://github.com///settings/environments/new` and create an environment called `pypi`. -- Set "Deployment branches and tags" to only allow tags `v*` to use the new environment. +- Set "Deployment branches and tags" to allow only the `main` branch to use the new environment. - Go to [PyPI](https://pypi.org/) and login; if you have no account there, create one first. - Configure a [trusted publisher](https://docs.pypi.org/trusted-publishers/adding-a-publisher/). @@ -228,9 +226,8 @@ This makes the release step more dependable, because by accident wrong dependenc Also deliberately by the way, so this is also a security measure. If you want to know more, lookup something like: GitHub Actions cache poisoning. -Setting the `pypi` environment did not add security in the steps above. -You can (and should) use it for that way though. -This walkthrough is getting very long already, so more on how to set that up is in the [extra guides](extra_guides.md#github-security-enhancements). +Setting the `pypi` environment adds a bit of security by preventing other workflows from touching PyPI. +Some more advises on GitHub security can be found in the [extra guides](extra_guides.md#github-security-enhancements). Also in the extra guides you can find the [minimal steps](extra_guides.md#executable-apps) on how to build and publish a CLI from this template. Unless your project will be really simple (which it never will be), I would advise to make separate lib and app/cli projects for business logic and integration respectively. diff --git a/{{ cookiecutter.project_slug }}/.github/workflows/publish-docs.yaml b/{{ cookiecutter.project_slug }}/.github/workflows/publish-docs.yaml deleted file mode 100644 index 7b38935..0000000 --- a/{{ cookiecutter.project_slug }}/.github/workflows/publish-docs.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: Publish to GitHub Pages - -on: - release: - types: [published] - -# This job is kept separate from the publish to PyPI job (release.yaml) for security reasons - -jobs: - publish: - name: Publish to GitHub Pages - runs-on: ubuntu-latest - permissions: - contents: read - pages: write - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Setup environment - uses: ./.github/actions/setup-env - with: - enable-uv-cache: false # No caching to ensure correct dependencies for publishing - sync-uv: true - - - name: Build docs - run: uv run mkdocs build - - - name: Setup GitHub Pages - uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - - - name: Upload GitHub Pages artifact - uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 - with: - path: ./site - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/{{ cookiecutter.project_slug }}/.github/workflows/release-please.yaml b/{{ cookiecutter.project_slug }}/.github/workflows/release-please.yaml deleted file mode 100644 index 206b789..0000000 --- a/{{ cookiecutter.project_slug }}/.github/workflows/release-please.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: Release Please - -on: - push: - branches: - - main - -jobs: - release: - name: Release Please - runs-on: ubuntu-latest - environment: - name: release-please - steps: - - name: Release Please - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 - with: - {#- Escape curly braces for Cookiecutter. -#} - {%- raw %} - token: ${{ secrets.RELEASE_PLEASE_TOKEN }} - {%- endraw %} - # advanced configuration is needed as long as this issue is open: - # https://github.com/googleapis/release-please/issues/2561 - # both below are the defaults, but good to make the relation explicit - config-file: release-please-config.json - manifest-file: .release-please-manifest.json diff --git a/{{ cookiecutter.project_slug }}/.github/workflows/release.yaml b/{{ cookiecutter.project_slug }}/.github/workflows/release.yaml index 65d0767..8b1707f 100644 --- a/{{ cookiecutter.project_slug }}/.github/workflows/release.yaml +++ b/{{ cookiecutter.project_slug }}/.github/workflows/release.yaml @@ -1,11 +1,39 @@ -name: Publish to PyPI +name: Release Orchestration on: - release: - types: [published] + push: + branches: + - main jobs: + release: + name: Release Please + runs-on: ubuntu-latest + outputs: + {#- Escape curly braces for Cookiecutter. -#} + {%- raw %} + releases_created: ${{ steps.release-please.outputs.releases_created }} + {%- endraw %} + permissions: + contents: write + pull-requests: write + steps: + - id: release-please + name: Release Please + uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 + with: + # advanced configuration is needed as long as this issue is open: + # https://github.com/googleapis/release-please/issues/2561 + # both below are the defaults, but good to make the relation explicit + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + publish: + needs: release + {#- Escape curly braces for Cookiecutter. -#} + {%- raw %} + if: ${{ needs.release.outputs.releases_created == 'true' }} + {%- endraw %} name: Publish to PyPI runs-on: ubuntu-latest environment: @@ -13,7 +41,6 @@ jobs: permissions: id-token: write contents: read - steps: - name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -29,3 +56,40 @@ jobs: - name: Publish package run: uv publish + + publish-docs: + needs: release + {#- Escape curly braces for Cookiecutter. -#} + {%- raw %} + if: ${{ needs.release.outputs.releases_created == 'true' }} + {%- endraw %} + name: Publish to GitHub Pages + runs-on: ubuntu-latest + permissions: + contents: read + pages: write + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup environment + uses: ./.github/actions/setup-env + with: + enable-uv-cache: false # No caching to ensure correct dependencies for publishing + sync-uv: true + + - name: Build docs + run: uv run mkdocs build + + - name: Setup GitHub Pages + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 + + - name: Upload GitHub Pages artifact + uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 + with: + path: ./site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5