From cc8bed7de187aaed57e6b4ad589c1f2c8673cb26 Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Thu, 18 Sep 2025 21:19:51 +0200 Subject: [PATCH 1/6] ci(workflows): harden add-to-project against missing secret Improves the workflow to handle cases where the secret is not configured. - Adds a guard to check if the secret is present. - If missing, it posts an informative comment on the new issue and exits gracefully instead of failing the workflow run. Closes #58 --- .github/workflows/add-to-project.yml | 60 +++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 30df77e..bb3c905 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -3,13 +3,69 @@ name: Add issues to project on: issues: types: [opened] + workflow_dispatch: + inputs: + issue_number: + description: "Issue number to (re)sync into the project" + required: true + type: number + +permissions: + contents: read + issues: write jobs: add: runs-on: ubuntu-latest + steps: + - name: "Guard: PROJECT_TOKEN present?" + id: guard + run: | + if [ -z "${{ secrets.PROJECT_TOKEN }}" ]; then + echo "missing=true" >> "$GITHUB_OUTPUT" + fi + + - name: Resolve target issue/content id + id: target + if: always() + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 pinned + with: + result-encoding: string + script: | + const manual = context.eventName === 'workflow_dispatch'; + let number = manual ? Number(core.getInput('issue_number')) + : (context.payload.issue && context.payload.issue.number); + if (!number) { + core.setFailed('Missing issue_number (required for workflow_dispatch).'); + return; + } + const { data: issue } = await github.rest.issues.get({ ...context.repo, issue_number: number }); + core.setOutput('issue_number', String(number)); + core.setOutput('content_id', issue.node_id); + + - name: Inform when PROJECT_TOKEN is missing + if: steps.guard.outputs.missing == 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 pinned + with: + script: | + const issue_number = Number('${{ steps.target.outputs.issue_number || 0 }}'); + if (!issue_number) { core.info('No issue number; skipping comment.'); return; } + const body = [ + "⚠️ Project auto-add skipped: missing `PROJECT_TOKEN` secret.", + "", + "Create a **Personal Access Token (classic)** with scopes **`repo`** + **`project`**", + "and add it as a repository secret named **`PROJECT_TOKEN`**.", + "", + "Docs: ", + "- PAT: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token", + "- Repo secrets: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository" + ].join("\n"); + await github.rest.issues.createComment({ ...context.repo, issue_number, body }); + - name: Add to project - uses: actions/add-to-project@v0.5.0 + if: steps.guard.outputs.missing != 'true' + uses: actions/add-to-project@31b3f3ccdc584546fc445612dec3f38ff5edb41c # v0.5.0 pinned with: project-url: https://github.com/users/thenarfer/projects/1 - github-token: ${{ secrets.PROJECT_TOKEN }} # PAT with repo + project scopes \ No newline at end of file + github-token: ${{ secrets.PROJECT_TOKEN }} \ No newline at end of file From c72c2254bd7477cf43a896f1073914d88e9ba752 Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Fri, 19 Sep 2025 12:56:32 +0000 Subject: [PATCH 2/6] Add content-id to add-to-project workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass content-id to actions/add-to-project (manual dispatch currently no-ops). You resolve content_id but don’t pass it to the action. Manual runs lack context and won’t add anything. Add the input unconditionally. --- .github/workflows/add-to-project.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index bb3c905..ea1138c 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -68,4 +68,5 @@ jobs: uses: actions/add-to-project@31b3f3ccdc584546fc445612dec3f38ff5edb41c # v0.5.0 pinned with: project-url: https://github.com/users/thenarfer/projects/1 - github-token: ${{ secrets.PROJECT_TOKEN }} \ No newline at end of file + github-token: ${{ secrets.PROJECT_TOKEN }} + content-id: ${{ steps.target.outputs.content_id }} From 998774b8c4c618276a1a467421a8731216401eef Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:12:51 +0000 Subject: [PATCH 3/6] Update condition for adding to project in workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing content-id fixes the manual path - This addresses the earlier review about no‑op manual dispatch. Consider also guarding on a non‑empty content_id. --- .github/workflows/add-to-project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index ea1138c..6684b64 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -64,7 +64,7 @@ jobs: await github.rest.issues.createComment({ ...context.repo, issue_number, body }); - name: Add to project - if: steps.guard.outputs.missing != 'true' + if: steps.guard.outputs.missing != 'true' && steps.target.outputs.content_id != '' uses: actions/add-to-project@31b3f3ccdc584546fc445612dec3f38ff5edb41c # v0.5.0 pinned with: project-url: https://github.com/users/thenarfer/projects/1 From 9eada48653c8e5029acaf04a7118e44543e6ea12 Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:14:55 +0000 Subject: [PATCH 4/6] Add guard for missing PROJECT_TOKEN in workflow Currently missing is only set when absent. Setting missing=false when present reduces ambiguity in later conditions. --- .github/workflows/add-to-project.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 6684b64..f30bbce 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -24,6 +24,8 @@ jobs: run: | if [ -z "${{ secrets.PROJECT_TOKEN }}" ]; then echo "missing=true" >> "$GITHUB_OUTPUT" + else + echo "missing=false" >> "$GITHUB_OUTPUT" fi - name: Resolve target issue/content id From 5d9c9ca1bac5e1c040bce309cde6168a12fddbd3 Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:15:57 +0000 Subject: [PATCH 5/6] Add github-token and improve issue number validation 29-46: Target resolution step is solid; consider explicit token and minor hardening Logic works for both triggers. Optionally pass the token explicitly and guard against NaN. --- .github/workflows/add-to-project.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index f30bbce..701c498 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -34,11 +34,12 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 pinned with: result-encoding: string + github-token: ${{ github.token }} script: | const manual = context.eventName === 'workflow_dispatch'; let number = manual ? Number(core.getInput('issue_number')) : (context.payload.issue && context.payload.issue.number); - if (!number) { + if (!number || Number.isNaN(number)) { core.setFailed('Missing issue_number (required for workflow_dispatch).'); return; } From acdef16f8f009f10bdc60bde12dc6ddd704bf49f Mon Sep 17 00:00:00 2001 From: Marius Trovik <62913125+thenarfer@users.noreply.github.com> Date: Fri, 19 Sep 2025 13:18:25 +0000 Subject: [PATCH 6/6] =?UTF-8?q?Avoid=20duplicate=20=E2=80=9Cmissing=20toke?= =?UTF-8?q?n=E2=80=9D=20comments;=20update=20PAT=20guidance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 47-65: Avoid duplicate “missing token” comments; update PAT guidance Check existing issue comments before creating a new one to avoid spam — apply the diff below. Update the user-facing text: fine‑grained PATs are supported (GA Mar 18, 2025). Acceptable tokens: classic PAT with scopes repo + project, or a fine‑grained PAT scoped to the target owner/repos with Projects (v2) read/write and repo-level permissions (issues: read, pull_requests: read). Token owner must have required access. --- .github/workflows/add-to-project.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/add-to-project.yml b/.github/workflows/add-to-project.yml index 701c498..638219a 100644 --- a/.github/workflows/add-to-project.yml +++ b/.github/workflows/add-to-project.yml @@ -64,6 +64,9 @@ jobs: "- PAT: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token", "- Repo secrets: https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository" ].join("\n"); + const { data: comments } = await github.rest.issues.listComments({ ...context.repo, issue_number, per_page: 100 }); + const seen = comments.some(c => c.body?.includes('Project auto-add skipped: missing `PROJECT_TOKEN`')); + if (seen) { core.info('Notice already present; skipping.'); return; } await github.rest.issues.createComment({ ...context.repo, issue_number, body }); - name: Add to project