Deploy the skills catalog to GitHub Pages on push to main. - #7
Merged
Conversation
This was referenced Sep 3, 2026
napetrov
added a commit
that referenced
this pull request
Sep 3, 2026
…tions zizmor fails `main` with five high findings, all of them in the Pages workflow added in #7: error[excessive-permissions] deploy-github-page.yml:13 pages: write error[excessive-permissions] deploy-github-page.yml:14 id-token: write error[unpinned-uses] deploy-github-page.yml:57 actions/configure-pages@v5 error[unpinned-uses] deploy-github-page.yml:60 actions/upload-pages-artifact@v3 error[unpinned-uses] deploy-github-page.yml:73 actions/deploy-pages@v5 Permissions. `pages: write` and `id-token: write` were granted at the workflow level, which hands them to both jobs. Only `deploy` needs them, and `build` is the job that should least have them: it checks out a second branch and runs `npm ci` and `npm run build` over its lockfile, which is the one place in this workflow where third-party code executes. A token that can publish the site or mint an OIDC identity does not belong in the job running someone else's postinstall script. Workflow level is now `contents: read`, with the two write scopes on `deploy`. Pins. Every other action in this repository is pinned by commit SHA; these three arrived as tags. Each is pinned to the SHA the tag it was using already resolved to, so nothing about what runs changes: actions/configure-pages v5 -> 983d7736... (v5.0.0) actions/upload-pages-artifact v3 -> 56afc609... (v3.0.1) actions/deploy-pages v5 -> 368f8252... (v5.0.1) Newer majors exist — configure-pages v6.0.0 and upload-pages-artifact v5.0.0 — and are deliberately left alone. Pinning and upgrading are different changes with different risk, and dependabot will propose the upgrades with a CI run attached. Verified with the same digest-pinned zizmor image security.yml uses: no findings, where the same command reported 5 high before. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
This was referenced Sep 3, 2026
xaleryb
added a commit
that referenced
this pull request
Sep 3, 2026
…hat needs it
Scoping the write permissions to `deploy` leaves `build` with `pages: none`, and
`build` still runs `Setup Pages`. actions/configure-pages GETs
/repos/{owner}/{repo}/pages, that endpoint is not public — an unauthenticated
request answers 404, not 200 — and with `enablement` at its default of false the
action's own error path is `core.error(...); throw`, which index.js turns into
`core.setFailed(error); process.exit(1)`. So `build` fails, `deploy` never runs
behind `needs: build`, and the site stops updating. The workflow has no
`pull_request` trigger, so no pull request can show this; it appears on the first
push to main after the merge.
The scope is granted rather than the step removed, because the step was doing
something worth doing and was simply never connected. base_path is the path
GitHub actually serves the site under, read from the repository's Pages
configuration; #7 copied the step out of GitHub's Pages starter workflow but
hardcoded `SITE_BASE: /skills/` instead of consuming it, left the step with no
`id` — which makes its outputs unreferenceable — and placed it after the build it
was meant to configure. So the step is moved above the build, given `id: pages`,
and its output feeds SITE_BASE.
The hardcode is a duplicate of a fact GitHub already holds, and it is wrong as
soon as the repository is renamed or a custom domain is set: base_path is then ''
and every asset URL has to lose its /skills/ prefix, which is every stylesheet
and all three woff2 fonts.
`contents: read` is restated in the job block because a job's permissions replace
the workflow-level map rather than adding to it, and the two checkouts need it.
`deploy` needs no contents: deploy-pages only calls the pages/deployments
endpoints and reads the artifact over ACTIONS_RUNTIME_TOKEN.
Verified: built the site from `github_page_src` against the `main` catalog with
SITE_BASE=/skills/ and with SITE_BASE=/skills, which is what base_path yields
here — `diff -r` reports the dist trees byte-for-byte identical, because
astro.config.mjs normalises the value. With SITE_BASE='' the assets move to the
domain root, which is the custom-domain case the hardcode gets wrong. actionlint
clean; zizmor at the same flags CI uses reports the 5 high findings on main and
none on this branch.
Signed-off-by: Rybkin <alexander.rybkin@intel.com>
xaleryb
pushed a commit
that referenced
this pull request
Sep 3, 2026
…tions zizmor fails `main` with five high findings, all of them in the Pages workflow added in #7: error[excessive-permissions] deploy-github-page.yml:13 pages: write error[excessive-permissions] deploy-github-page.yml:14 id-token: write error[unpinned-uses] deploy-github-page.yml:57 actions/configure-pages@v5 error[unpinned-uses] deploy-github-page.yml:60 actions/upload-pages-artifact@v3 error[unpinned-uses] deploy-github-page.yml:73 actions/deploy-pages@v5 Permissions. `pages: write` and `id-token: write` were granted at the workflow level, which hands them to both jobs. Only `deploy` needs them, and `build` is the job that should least have them: it checks out a second branch and runs `npm ci` and `npm run build` over its lockfile, which is the one place in this workflow where third-party code executes. A token that can publish the site or mint an OIDC identity does not belong in the job running someone else's postinstall script. Workflow level is now `contents: read`, with the two write scopes on `deploy`. Pins. Every other action in this repository is pinned by commit SHA; these three arrived as tags. Each is pinned to the SHA the tag it was using already resolved to, so nothing about what runs changes: actions/configure-pages v5 -> 983d7736... (v5.0.0) actions/upload-pages-artifact v3 -> 56afc609... (v3.0.1) actions/deploy-pages v5 -> 368f8252... (v5.0.1) Newer majors exist — configure-pages v6.0.0 and upload-pages-artifact v5.0.0 — and are deliberately left alone. Pinning and upgrading are different changes with different risk, and dependabot will propose the upgrades with a CI run attached. Verified with the same digest-pinned zizmor image security.yml uses: no findings, where the same command reported 5 high before. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
xaleryb
added a commit
that referenced
this pull request
Sep 3, 2026
…hat needs it
Scoping the write permissions to `deploy` leaves `build` with `pages: none`, and
`build` still runs `Setup Pages`. actions/configure-pages GETs
/repos/{owner}/{repo}/pages, that endpoint is not public — an unauthenticated
request answers 404, not 200 — and with `enablement` at its default of false the
action's own error path is `core.error(...); throw`, which index.js turns into
`core.setFailed(error); process.exit(1)`. So `build` fails, `deploy` never runs
behind `needs: build`, and the site stops updating. The workflow has no
`pull_request` trigger, so no pull request can show this; it appears on the first
push to main after the merge.
The scope is granted rather than the step removed, because the step was doing
something worth doing and was simply never connected. base_path is the path
GitHub actually serves the site under, read from the repository's Pages
configuration; #7 copied the step out of GitHub's Pages starter workflow but
hardcoded `SITE_BASE: /skills/` instead of consuming it, left the step with no
`id` — which makes its outputs unreferenceable — and placed it after the build it
was meant to configure. So the step is moved above the build, given `id: pages`,
and its output feeds SITE_BASE.
The hardcode is a duplicate of a fact GitHub already holds, and it is wrong as
soon as the repository is renamed or a custom domain is set: base_path is then ''
and every asset URL has to lose its /skills/ prefix, which is every stylesheet
and all three woff2 fonts.
`contents: read` is restated in the job block because a job's permissions replace
the workflow-level map rather than adding to it, and the two checkouts need it.
`deploy` needs no contents: deploy-pages only calls the pages/deployments
endpoints and reads the artifact over ACTIONS_RUNTIME_TOKEN.
Verified: built the site from `github_page_src` against the `main` catalog with
SITE_BASE=/skills/ and with SITE_BASE=/skills, which is what base_path yields
here — `diff -r` reports the dist trees byte-for-byte identical, because
astro.config.mjs normalises the value. With SITE_BASE='' the assets move to the
domain root, which is the custom-domain case the hardcode gets wrong. actionlint
clean; zizmor at the same flags CI uses reports the 5 high findings on main and
none on this branch.
Signed-off-by: Rybkin <alexander.rybkin@intel.com>
xaleryb
pushed a commit
that referenced
this pull request
Sep 3, 2026
…tions zizmor fails `main` with five high findings, all of them in the Pages workflow added in #7: error[excessive-permissions] deploy-github-page.yml:13 pages: write error[excessive-permissions] deploy-github-page.yml:14 id-token: write error[unpinned-uses] deploy-github-page.yml:57 actions/configure-pages@v5 error[unpinned-uses] deploy-github-page.yml:60 actions/upload-pages-artifact@v3 error[unpinned-uses] deploy-github-page.yml:73 actions/deploy-pages@v5 Permissions. `pages: write` and `id-token: write` were granted at the workflow level, which hands them to both jobs. Only `deploy` needs them, and `build` is the job that should least have them: it checks out a second branch and runs `npm ci` and `npm run build` over its lockfile, which is the one place in this workflow where third-party code executes. A token that can publish the site or mint an OIDC identity does not belong in the job running someone else's postinstall script. Workflow level is now `contents: read`, with the two write scopes on `deploy`. Pins. Every other action in this repository is pinned by commit SHA; these three arrived as tags. Each is pinned to the SHA the tag it was using already resolved to, so nothing about what runs changes: actions/configure-pages v5 -> 983d7736... (v5.0.0) actions/upload-pages-artifact v3 -> 56afc609... (v3.0.1) actions/deploy-pages v5 -> 368f8252... (v5.0.1) Newer majors exist — configure-pages v6.0.0 and upload-pages-artifact v5.0.0 — and are deliberately left alone. Pinning and upgrading are different changes with different risk, and dependabot will propose the upgrades with a CI run attached. Verified with the same digest-pinned zizmor image security.yml uses: no findings, where the same command reported 5 high before. Signed-off-by: Nikolay Petrov <nikolay.a.petrov@intel.com>
xaleryb
added a commit
that referenced
this pull request
Sep 3, 2026
…hat needs it
Scoping the write permissions to `deploy` leaves `build` with `pages: none`, and
`build` still runs `Setup Pages`. actions/configure-pages GETs
/repos/{owner}/{repo}/pages, that endpoint is not public — an unauthenticated
request answers 404, not 200 — and with `enablement` at its default of false the
action's own error path is `core.error(...); throw`, which index.js turns into
`core.setFailed(error); process.exit(1)`. So `build` fails, `deploy` never runs
behind `needs: build`, and the site stops updating. The workflow has no
`pull_request` trigger, so no pull request can show this; it appears on the first
push to main after the merge.
The scope is granted rather than the step removed, because the step was doing
something worth doing and was simply never connected. base_path is the path
GitHub actually serves the site under, read from the repository's Pages
configuration; #7 copied the step out of GitHub's Pages starter workflow but
hardcoded `SITE_BASE: /skills/` instead of consuming it, left the step with no
`id` — which makes its outputs unreferenceable — and placed it after the build it
was meant to configure. So the step is moved above the build, given `id: pages`,
and its output feeds SITE_BASE.
The hardcode is a duplicate of a fact GitHub already holds, and it is wrong as
soon as the repository is renamed or a custom domain is set: base_path is then ''
and every asset URL has to lose its /skills/ prefix, which is every stylesheet
and all three woff2 fonts.
`contents: read` is restated in the job block because a job's permissions replace
the workflow-level map rather than adding to it, and the two checkouts need it.
`deploy` needs no contents: deploy-pages only calls the pages/deployments
endpoints and reads the artifact over ACTIONS_RUNTIME_TOKEN.
Verified: built the site from `github_page_src` against the `main` catalog with
SITE_BASE=/skills/ and with SITE_BASE=/skills, which is what base_path yields
here — `diff -r` reports the dist trees byte-for-byte identical, because
astro.config.mjs normalises the value. With SITE_BASE='' the assets move to the
domain root, which is the custom-domain case the hardcode gets wrong. actionlint
clean; zizmor at the same flags CI uses reports the 5 high findings on main and
none on this branch.
Signed-off-by: Rybkin <alexander.rybkin@intel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.