From 43b163388c3386a897b3ccf7835e639012476434 Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 01:59:10 +0900 Subject: [PATCH 1/6] Use GitHub App for VPM release updates --- .github/workflows/update-vpm.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-vpm.yml b/.github/workflows/update-vpm.yml index 8588c59..42e6261 100644 --- a/.github/workflows/update-vpm.yml +++ b/.github/workflows/update-vpm.yml @@ -41,7 +41,7 @@ on: type: string permissions: - contents: write + contents: read concurrency: group: vpm-repository-update @@ -72,10 +72,19 @@ jobs: echo "VPM repository default branch must be master." exit 1 + - name: Create VPM repository GitHub App token + id: app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ secrets.APP_CLIENT_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + permission-contents: write + - name: Checkout VPM repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: master + token: ${{ steps.app-token.outputs.token }} persist-credentials: true - name: Set up Python 3.12 @@ -94,9 +103,11 @@ jobs: - name: Commit and push listing if: steps.update.outputs.changed == 'true' + env: + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "${APP_SLUG}[bot]" + git config user.email "${APP_SLUG}[bot]@users.noreply.github.com" git add -- vpm.json git commit -m "Add ${PACKAGE_NAME} ${VERSION}" git push origin "HEAD:master" From e741511c16eec03a3ba76f850b97d1da47306178 Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 01:59:29 +0900 Subject: [PATCH 2/6] Use GitHub App for VPM yank updates --- .github/workflows/sync-vpm-yanks.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync-vpm-yanks.yml b/.github/workflows/sync-vpm-yanks.yml index 1a1edd4..ddc652f 100644 --- a/.github/workflows/sync-vpm-yanks.yml +++ b/.github/workflows/sync-vpm-yanks.yml @@ -21,7 +21,7 @@ on: type: string permissions: - contents: write + contents: read concurrency: group: vpm-repository-update @@ -45,10 +45,19 @@ jobs: echo "VPM repository default branch must be master." exit 1 + - name: Create VPM repository GitHub App token + id: app-token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + client-id: ${{ secrets.APP_CLIENT_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + permission-contents: write + - name: Checkout VPM repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: master + token: ${{ steps.app-token.outputs.token }} persist-credentials: true - name: Set up Python 3.12 @@ -80,9 +89,11 @@ jobs: - name: Commit and push yank projection if: steps.sync.outputs.changed == 'true' + env: + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "${APP_SLUG}[bot]" + git config user.email "${APP_SLUG}[bot]@users.noreply.github.com" git add -- vpm.json git commit -m "Sync ${PACKAGE_NAME} yank policy" git push origin "HEAD:master" From 6391ab18a4ddd9325d0672a59cb318e42d3b1d8e Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 01:59:58 +0900 Subject: [PATCH 3/6] Document VPM GitHub App authentication --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 195dc3e..90a14bc 100644 --- a/README.md +++ b/README.md @@ -42,15 +42,17 @@ For each Pure Base version, generated links use: This keeps historical metadata stable even if the default branch changes later. -## Required Pure Base configuration +## Required GitHub App configuration -Configure the following in `Penguin-Repository/Pure-Base`: +Configure the following in both `Penguin-Repository/Pure-Base` and `Penguin-Repository/VPM-Repository`: -- Repository variable `VPM_REPOSITORY`: `Penguin-Repository/VPM-Repository` -- Release-environment secrets `APP_CLIENT_ID` and `APP_PRIVATE_KEY` -- A GitHub App installation that can write contents in both repositories +- Repository or environment secrets `APP_CLIENT_ID` and `APP_PRIVATE_KEY` +- A GitHub App installation covering both repositories +- GitHub App repository permission `Contents: Read and write` -The receiving workflow uses its scoped `GITHUB_TOKEN` with `contents: write`; it does not need copies of the GitHub App private key. +Configure repository variable `VPM_REPOSITORY` in `Penguin-Repository/Pure-Base` as `Penguin-Repository/VPM-Repository`. + +The receiving workflows create a repository-scoped installation token with `contents: write`, use it for checkout and direct pushes to `master`, and commit as the GitHub App bot. The workflow-level `GITHUB_TOKEN` remains read-only and is used only for validation requests. ## Dispatch payload From e87502785401f93d4ebff95fc74181b444628e33 Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 05:05:43 +0900 Subject: [PATCH 4/6] Address GitHub App identity review feedback --- .github/workflows/update-vpm.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-vpm.yml b/.github/workflows/update-vpm.yml index 42e6261..18cf631 100644 --- a/.github/workflows/update-vpm.yml +++ b/.github/workflows/update-vpm.yml @@ -80,6 +80,17 @@ jobs: private-key: ${{ secrets.APP_PRIVATE_KEY }} permission-contents: write + - name: Resolve GitHub App bot identity + id: app-bot + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + run: | + bot_login="${APP_SLUG}[bot]" + bot_id="$(gh api "users/${bot_login}" --jq '.id')" + echo "name=${bot_login}" >> "$GITHUB_OUTPUT" + echo "email=${bot_id}+${bot_login}@users.noreply.github.com" >> "$GITHUB_OUTPUT" + - name: Checkout VPM repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -104,10 +115,11 @@ jobs: - name: Commit and push listing if: steps.update.outputs.changed == 'true' env: - APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + APP_BOT_NAME: ${{ steps.app-bot.outputs.name }} + APP_BOT_EMAIL: ${{ steps.app-bot.outputs.email }} run: | - git config user.name "${APP_SLUG}[bot]" - git config user.email "${APP_SLUG}[bot]@users.noreply.github.com" + git config user.name "$APP_BOT_NAME" + git config user.email "$APP_BOT_EMAIL" git add -- vpm.json git commit -m "Add ${PACKAGE_NAME} ${VERSION}" git push origin "HEAD:master" From 517ede7ccf3a23f2aad2957b42b62f6f2362bee9 Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 05:06:05 +0900 Subject: [PATCH 5/6] Address GitHub App identity review feedback --- .github/workflows/sync-vpm-yanks.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sync-vpm-yanks.yml b/.github/workflows/sync-vpm-yanks.yml index ddc652f..e34dfaf 100644 --- a/.github/workflows/sync-vpm-yanks.yml +++ b/.github/workflows/sync-vpm-yanks.yml @@ -53,6 +53,17 @@ jobs: private-key: ${{ secrets.APP_PRIVATE_KEY }} permission-contents: write + - name: Resolve GitHub App bot identity + id: app-bot + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + run: | + bot_login="${APP_SLUG}[bot]" + bot_id="$(gh api "users/${bot_login}" --jq '.id')" + echo "name=${bot_login}" >> "$GITHUB_OUTPUT" + echo "email=${bot_id}+${bot_login}@users.noreply.github.com" >> "$GITHUB_OUTPUT" + - name: Checkout VPM repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -90,10 +101,11 @@ jobs: - name: Commit and push yank projection if: steps.sync.outputs.changed == 'true' env: - APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + APP_BOT_NAME: ${{ steps.app-bot.outputs.name }} + APP_BOT_EMAIL: ${{ steps.app-bot.outputs.email }} run: | - git config user.name "${APP_SLUG}[bot]" - git config user.email "${APP_SLUG}[bot]@users.noreply.github.com" + git config user.name "$APP_BOT_NAME" + git config user.email "$APP_BOT_EMAIL" git add -- vpm.json git commit -m "Sync ${PACKAGE_NAME} yank policy" git push origin "HEAD:master" From f0326a6dd84a9b55a8173385bda7a3ac0deed613 Mon Sep 17 00:00:00 2001 From: Penguin <50603637+PenguinDOOM@users.noreply.github.com> Date: Wed, 5 Aug 2026 05:06:26 +0900 Subject: [PATCH 6/6] Clarify GitHub App secret requirements --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90a14bc..1d55255 100644 --- a/README.md +++ b/README.md @@ -46,13 +46,13 @@ This keeps historical metadata stable even if the default branch changes later. Configure the following in both `Penguin-Repository/Pure-Base` and `Penguin-Repository/VPM-Repository`: -- Repository or environment secrets `APP_CLIENT_ID` and `APP_PRIVATE_KEY` +- Repository secrets `APP_CLIENT_ID` and `APP_PRIVATE_KEY` - A GitHub App installation covering both repositories - GitHub App repository permission `Contents: Read and write` Configure repository variable `VPM_REPOSITORY` in `Penguin-Repository/Pure-Base` as `Penguin-Repository/VPM-Repository`. -The receiving workflows create a repository-scoped installation token with `contents: write`, use it for checkout and direct pushes to `master`, and commit as the GitHub App bot. The workflow-level `GITHUB_TOKEN` remains read-only and is used only for validation requests. +The receiving workflows create a repository-scoped installation token with `contents: write`, use it for checkout and direct pushes to `master`, and commit as the GitHub App bot using its ID-based GitHub noreply address. The workflow-level `GITHUB_TOKEN` remains read-only and is used only for validation requests. ## Dispatch payload