Skip to content

chore(deps): update dependency cosign to v3.1.2 #10144

chore(deps): update dependency cosign to v3.1.2

chore(deps): update dependency cosign to v3.1.2 #10144

Workflow file for this run

# SPDX-FileCopyrightText: 2026 Alexey Zhokhov
# SPDX-License-Identifier: Apache-2.0
name: Docs
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
schedule:
- cron: '17 4 * * *'
permissions:
actions: read
contents: read
env:
DOCS_SITE_URL: https://jackin.tailrocks.com
JACKIN_REPO_BLOB_URL: https://github.com/jackin-project/jackin/blob/main
JACKIN_REPO_EDIT_URL: https://github.com/jackin-project/jackin/edit/main
concurrency:
group: pages-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# Schedule (cron) runs only `check-deployed` (line ~210) by design —
# all other jobs gate themselves out on `event_name != 'schedule'`.
# The cron path verifies live deployed-site links; it has nothing to
# validate against the source tree at schedule time.
changes:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
docs: ${{ steps.dispatch.outputs.docs || steps.filter.outputs.docs }}
source: ${{ steps.dispatch.outputs.source || steps.filter.outputs.source }}
result-reuse: ${{ steps.docs-result.outputs.hit }}
result-name: ${{ steps.docs-result.outputs.name }}
docs-xtask-contract: ${{ steps.contracts.outputs.docs-xtask }}
deployment-reuse: ${{ steps.deployed.outputs.reuse }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
- name: Force docs=true on workflow_dispatch
id: dispatch
if: github.event_name == 'workflow_dispatch'
shell: bash
run: |
{
echo "docs=true"
echo "source=true"
} >> "$GITHUB_OUTPUT"
- name: Resolve Docs xtask contract
id: contracts
run: echo "docs-xtask=$(scripts/ci/docs-xtask-contract.sh)" >> "$GITHUB_OUTPUT"
- name: Classify changed paths
id: filter
if: github.event_name != 'workflow_dispatch'
uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
with:
token: ""
base: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }}
filters: |
docs:
- 'AGENTS.md'
- 'BRANCHING.md'
- 'COMMITS.md'
- 'CONTRIBUTING.md'
- 'PROJECT_STRUCTURE.md'
- 'PULL_REQUESTS.md'
- 'README.md'
- 'RULES.md'
- 'TESTING.md'
- '.github/**/*.md'
- '.github/**/*.yml'
- '.github/workflows/docs.yml'
- '.github/actions/check-deployed-docs/**'
- 'scripts/ci/docs-xtask-contract.sh'
- 'scripts/ci/docs-site-contract.sh'
- 'scripts/ci/codebook-contract.sh'
- 'docs/**'
source:
- 'crates/**'
- 'docker/**/*.fish'
- 'docker/**/*.sh'
- 'docker/**/*.toml'
- '.github/workflows/docs.yml'
- 'scripts/ci/docs-xtask-contract.sh'
- 'scripts/ci/docs-site-contract.sh'
- 'scripts/ci/codebook-contract.sh'
- name: Find input-identical successful Docs result
id: docs-result
shell: bash
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
digest=$(
{
printf 'tracked-paths=%s\n' "$(git ls-files -z | sha256sum | cut -d ' ' -f 1)"
while IFS= read -r -d '' path; do
printf '%s\0%s\n' "$path" "$(git hash-object "$path")"
done < <(
git ls-files -z -- \
'.github/actions/check-deployed-docs/**' \
'.github/actions/download-ci-xtask/**' \
'.github/**/*.md' \
'.github/**/*.yml' \
'.github/workflows/docs.yml' \
'AGENTS.md' \
'BRANCHING.md' \
'COMMITS.md' \
'CONTRIBUTING.md' \
'Cargo.lock' \
'Cargo.toml' \
'PROJECT_STRUCTURE.md' \
'PULL_REQUESTS.md' \
'README.md' \
'RULES.md' \
'TESTING.md' \
'crates/**/*.rs' \
'crates/**/*.toml' \
'crates/*/README.md' \
'docker/**/*.fish' \
'docker/**/*.sh' \
'docker/**/*.toml' \
'docs/**' \
'mise.lock' \
'mise.toml' \
'scripts/ci/docs-xtask-contract.sh' \
'scripts/ci/docs-site-contract.sh' \
'scripts/ci/codebook-contract.sh'
)
} | sha256sum | cut -d ' ' -f 1
)
name="docs-result-v1-${digest}"
artifact_id=
if ! artifact_id=$(
gh api "repos/${REPOSITORY}/actions/artifacts?name=${name}&per_page=10" \
--jq '.artifacts | map(select(.expired == false)) | first | .id // empty'
); then
echo "::warning::Docs result lookup failed; running the complete selected contract"
artifact_id=
fi
if [ -n "$artifact_id" ]; then
echo "::notice::reusing input-identical successful Docs result"
hit=true
else
hit=false
fi
{
echo "hit=$hit"
echo "name=$name"
} >> "$GITHUB_OUTPUT"
- name: Find semantically identical successful Pages deployment
id: deployed
if: >-
github.event_name == 'push' ||
github.event_name == 'workflow_dispatch'
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
reuse=false
deployments=$(
gh api "repos/${REPOSITORY}/deployments?environment=github-pages&per_page=10" \
--jq '.[] | [.id, .sha] | @tsv'
)
while IFS=$'\t' read -r deployment_id source_sha; do
if [ -z "$deployment_id" ] || [ -z "$source_sha" ]; then
continue
fi
state=$(
gh api "repos/${REPOSITORY}/deployments/${deployment_id}/statuses?per_page=1" \
--jq '.[0].state // empty'
)
if [ "$state" != success ]; then
continue
fi
if ! git cat-file -e "$source_sha^{commit}" 2>/dev/null && \
! git fetch --no-tags --depth=1 origin "$source_sha"; then
break
fi
if [ "$(scripts/ci/docs-site-contract.sh "$source_sha")" = \
"$(scripts/ci/docs-site-contract.sh)" ]; then
echo "::notice::reusing semantically identical successful Pages deployment"
reuse=true
fi
break
done <<< "$deployments"
echo "reuse=$reuse" >> "$GITHUB_OUTPUT"
# The docs site links to repository files via the <RepoFile path="…" />
# component, which renders a `blob/main` URL that lychee remaps to the
# PR checkout. A source-only PR that renames or deletes a referenced
# file would not match the docs path filter and would silently merge
# with broken links. Run a cheap standalone repo-link check on every
# non-schedule event so source renames cannot bypass the docs link
# contract documented in docs/AGENTS.md.
repo-link-check:
if: github.event_name != 'schedule' && needs.changes.outputs.result-reuse != 'true'
needs: changes
runs-on: ubuntu-latest
timeout-minutes: 15
env:
DOCS_XTASK: ${{ github.workspace }}/.ci-tools/GitHub/jackin-xtask
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Setup mise
uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4
with:
version: "2026.6.11"
cache_key_prefix: "mise-v2"
cache_save: ${{ github.ref == 'refs/heads/main' }}
working_directory: docs
install_args: "bun lychee"
github_token: ${{ secrets.GH_READONLY_TOKEN }}
- uses: ./.github/actions/download-ci-xtask
with:
lane: GitHub
xtask-contract: ${{ needs.changes.outputs.docs-xtask-contract }}
include-tools: "false"
# Plan 049 residual: generate crate README → Fumadocs pages so repo-link
# checks see the same generated MDX the docs build ships (gitignored).
- name: Generate crate pages
working-directory: docs
run: bun run scripts/gen-crate-pages.ts
- name: Register xtask problem matcher
run: echo "::add-matcher::.github/problem-matchers/xtask.json"
- name: Check source repository links
run: |
"$DOCS_XTASK" docs repo-links
# README links are not part of the generated docs site. Check them live
# without cache so a malformed or removed destination fails this PR.
- name: Check README links
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
MISE_CONFIG_FILE=docs/mise.toml mise exec -- lychee \
--config docs/lychee.toml \
--cache=false \
--root-dir "${{ github.workspace }}" \
README.md
- name: Check brand prose
run: |
"$DOCS_XTASK" docs brand
- name: Check behavioral-spec test citations
run: |
env -u CI "$DOCS_XTASK" docs specs
- name: Check roadmap sidebar completeness
run: |
"$DOCS_XTASK" roadmap audit
- name: Check research sidebar completeness
run: |
"$DOCS_XTASK" research check
docs-link-check:
needs: changes
if: >-
needs.changes.outputs.docs == 'true' &&
(needs.changes.outputs.result-reuse != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true'))
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Find repository-wide successful link result
id: link-result
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
REPOSITORY_ID: ${{ github.event.repository.id }}
run: |
set -euo pipefail
name="docs-links-v2-${RUNNER_OS}-$(scripts/ci/docs-link-contract.sh)"
artifact=$(
gh api "repos/${REPOSITORY}/actions/artifacts?name=${name}&per_page=10" \
| jq -c --argjson repository_id "$REPOSITORY_ID" \
'[.artifacts[] | select(.expired == false and .workflow_run.head_repository_id == $repository_id)] | sort_by(.created_at) | last // {}'
)
artifact_id=$(jq -r '.id // empty' <<< "$artifact")
created_at=$(jq -r '.created_at // empty' <<< "$artifact")
verified=false
refresh=true
if [ -n "$artifact_id" ]; then
created_epoch=$(date -u -d "$created_at" +%s)
if [ $(( $(date -u +%s) - created_epoch )) -lt 259200 ]; then
verified=true
refresh=false
fi
fi
{
echo "name=$name"
echo "refresh=$refresh"
echo "verified=$verified"
} >> "$GITHUB_OUTPUT"
- name: Restore input-identical built site
id: built-site
if: >-
steps.link-result.outputs.verified != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true')
shell: bash
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
name="docs-site-v3-${RUNNER_OS}-$(scripts/ci/docs-site-contract.sh)"
artifact_id=
exact=false
if ! artifact_id=$(
gh api "repos/${REPOSITORY}/actions/artifacts?name=${name}&per_page=10" \
--jq '.artifacts | map(select(.expired == false)) | first | .id // empty'
); then
echo "::warning::built-site artifact lookup failed; rebuilding the site"
artifact_id=
fi
if [ -n "$artifact_id" ]; then
exact=true
fi
if [ -n "$artifact_id" ]; then
mkdir -p docs/.output/public
gh api "repos/${REPOSITORY}/actions/artifacts/${artifact_id}/zip" \
> docs/.output/.site.zip
python3 -m zipfile -e docs/.output/.site.zip docs/.output/public
rm docs/.output/.site.zip
html=$(find docs/.output/public -type f -name '*.html' -print -quit)
if [ -n "$html" ]; then
echo "::notice::reusing input-identical built site"
hit=true
else
echo "::warning::built-site artifact is invalid; rebuilding the site"
rm -rf docs/.output/public
hit=false
exact=false
fi
else
hit=false
fi
{
echo "hit=$hit"
echo "exact=$exact"
echo "name=$name"
} >> "$GITHUB_OUTPUT"
- name: Setup mise
if: >-
steps.link-result.outputs.verified != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true')
uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4
with:
version: "2026.6.11"
cache_key_prefix: "mise-v2"
cache_save: ${{ github.ref == 'refs/heads/main' }}
working_directory: docs
install_args: ${{ steps.built-site.outputs.hit == 'true' && 'lychee' || 'bun node lychee' }}
github_token: ${{ secrets.GH_READONLY_TOKEN }}
- name: Cache bun modules
if: >-
(steps.link-result.outputs.verified != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true')) &&
steps.built-site.outputs.hit != 'true'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('docs/bun.lock') }}
restore-keys: bun-${{ runner.os }}-
- name: Install dependencies
if: >-
(steps.link-result.outputs.verified != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true')) &&
steps.built-site.outputs.hit != 'true'
working-directory: docs
run: bun ci
- name: Build site
if: >-
(steps.link-result.outputs.verified != 'true' ||
(github.ref == 'refs/heads/main' &&
needs.changes.outputs.deployment-reuse != 'true')) &&
steps.built-site.outputs.hit != 'true'
working-directory: docs
run: bun run build
- name: Cache lychee responses
if: steps.link-result.outputs.verified != 'true'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .lycheecache
key: lychee-v1-${{ runner.os }}-${{ hashFiles('docs/lychee.toml', 'scripts/ci/docs-link-check.sh') }}
restore-keys: lychee-v1-${{ runner.os }}-
- name: Check built site links
if: steps.link-result.outputs.verified != 'true'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
scripts/ci/docs-link-check.sh
- name: Stage repository-wide successful link result
if: steps.link-result.outputs.refresh == 'true'
run: |
mkdir -p ci-results
printf '%s\n' '${{ github.sha }}' > ci-results/docs-links
- name: Publish repository-wide successful link result
if: >-
steps.link-result.outputs.refresh == 'true' &&
(github.ref == 'refs/heads/main' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.link-result.outputs.name }}
path: ci-results/docs-links
compression-level: 0
retention-days: 7
- name: Publish input-identical built site
if: >-
steps.built-site.outcome != 'skipped' &&
steps.built-site.outputs.exact != 'true' &&
(github.ref == 'refs/heads/main' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.built-site.outputs.name }}
path: docs/.output/public
compression-level: 0
retention-days: 7
- name: Upload artifact
if: >-
needs.changes.outputs.deployment-reuse != 'true' &&
(github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main'))
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
with:
path: docs/.output/public
prepare-codebook:
needs: changes
if: >-
github.event_name != 'schedule' &&
needs.changes.outputs.result-reuse != 'true' &&
(needs.changes.outputs.docs == 'true' || needs.changes.outputs.source == 'true')
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Restore resolved Codebook binary
id: codebook-artifact
shell: bash
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
contract=$(scripts/ci/codebook-contract.sh)
name="codebook-lsp-v1-${RUNNER_OS}-${RUNNER_ARCH}-${contract}"
mkdir -p .ci-codebook
artifact_id=
if ! artifact_id=$(
gh api "repos/${REPOSITORY}/actions/artifacts?name=${name}&per_page=10" \
--jq '.artifacts[] | select(.expired == false) | .id' \
| head -n 1
); then
echo "::warning::Codebook artifact lookup failed; preparing the binary"
artifact_id=
fi
if [ -n "$artifact_id" ]; then
gh api "repos/${REPOSITORY}/actions/artifacts/${artifact_id}/zip" \
> .ci-codebook/.artifact.zip
python3 -m zipfile -e .ci-codebook/.artifact.zip .ci-codebook
rm .ci-codebook/.artifact.zip
hit=true
else
hit=false
fi
{
echo "hit=$hit"
echo "name=$name"
} >> "$GITHUB_OUTPUT"
- name: Build missing Codebook binary once
if: steps.codebook-artifact.outputs.hit != 'true'
uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4
with:
version: "2026.6.11"
cache_key_prefix: "mise-v2"
cache_save: ${{ github.ref == 'refs/heads/main' }}
install_args: "cargo-binstall cargo:codebook-lsp"
github_token: ${{ secrets.GH_READONLY_TOKEN }}
- name: Stage Codebook binary
shell: bash
run: |
set -euo pipefail
if [ "${{ steps.codebook-artifact.outputs.hit }}" != "true" ]; then
cp "$(mise which codebook-lsp)" .ci-codebook/codebook-lsp
strip .ci-codebook/codebook-lsp
fi
chmod +x .ci-codebook/codebook-lsp
- name: Publish resolved Codebook binary
if: >-
steps.codebook-artifact.outputs.hit != 'true' &&
(github.ref == 'refs/heads/main' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.codebook-artifact.outputs.name }}
path: .ci-codebook/codebook-lsp
compression-level: 0
retention-days: 7
spell-check-docs:
needs: [changes, prepare-codebook]
if: >-
github.event_name != 'schedule' &&
needs.changes.outputs.result-reuse != 'true' &&
needs.changes.outputs.docs == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download prepared Codebook binary
uses: ./.github/actions/download-codebook
- name: Run Codebook docs spell check
shell: bash
run: |
set -euo pipefail
spell_files=()
while IFS= read -r path; do
spell_files+=("$path")
done < <(
git ls-files \
'AGENTS.md' \
'BRANCHING.md' \
'COMMITS.md' \
'CONTRIBUTING.md' \
'PROJECT_STRUCTURE.md' \
'PULL_REQUESTS.md' \
'README.md' \
'RULES.md' \
'TESTING.md' \
'.github/**/*.md' \
'.github/**/*.yml' \
'docs/**/*.md' \
'docs/**/*.mdx'
)
printf 'Spell checking %s docs/prose file(s):\n' "${#spell_files[@]}"
printf ' %s\n' "${spell_files[@]}"
chmod +x .ci-codebook/codebook-lsp
.ci-codebook/codebook-lsp --root . lint --unique "${spell_files[@]}"
spell-check-source:
needs: [changes, prepare-codebook]
if: >-
github.event_name != 'schedule' &&
needs.changes.outputs.result-reuse != 'true' &&
needs.changes.outputs.source == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download prepared Codebook binary
uses: ./.github/actions/download-codebook
- name: Run Codebook source spell check
shell: bash
run: |
set -euo pipefail
spell_files=()
while IFS= read -r path; do
spell_files+=("$path")
done < <(
git ls-files \
'crates/**/*.rs' \
'crates/**/*.toml' \
'docker/**/*.fish' \
'docker/**/*.sh' \
'docker/**/*.toml' \
'docker/**/*.zsh'
)
printf 'Spell checking %s source file(s):\n' "${#spell_files[@]}"
printf ' %s\n' "${spell_files[@]}"
chmod +x .ci-codebook/codebook-lsp
.ci-codebook/codebook-lsp --root . lint --unique "${spell_files[@]}"
deploy:
# docs-link-check covers full-site lychee + docs build; repo-link-check
# covers <RepoFile /> path validity. Both must pass before publishing.
#
# GitHub Pages can report a terminal `deployment_failed` for a valid
# artifact, then accept the same artifact/SHA on the next deployment.
# Keep retries scoped to that opaque Pages handoff instead of rerunning
# the whole workflow or retrying source/build/link validation.
needs: [changes, docs-link-check, repo-link-check]
if: >-
always() &&
(github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main')) &&
needs.changes.outputs.deployment-reuse != 'true' &&
needs.docs-link-check.result == 'success' &&
(needs.repo-link-check.result == 'success' ||
needs.repo-link-check.result == 'skipped')
runs-on: ubuntu-latest
timeout-minutes: 35
outputs:
page-url: ${{ steps.deploy1.outputs.page_url || steps.deploy2.outputs.page_url || steps.deploy3.outputs.page_url }}
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deploy1.outputs.page_url || steps.deploy2.outputs.page_url || steps.deploy3.outputs.page_url }}
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Deploy to GitHub Pages
id: deploy1
continue-on-error: true
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
- name: Back off before Pages deploy retry 2
if: steps.deploy1.outcome == 'failure'
shell: bash
run: |
echo "::notice::GitHub Pages deployment failed on attempt 1; retrying after 30 seconds"
sleep 30
- name: Deploy to GitHub Pages (retry 2)
id: deploy2
if: steps.deploy1.outcome == 'failure'
continue-on-error: true
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
- name: Back off before Pages deploy retry 3
if: steps.deploy1.outcome == 'failure' && steps.deploy2.outcome == 'failure'
shell: bash
run: |
echo "::notice::GitHub Pages deployment failed on attempt 2; retrying after 60 seconds"
sleep 60
- name: Deploy to GitHub Pages (retry 3)
id: deploy3
if: steps.deploy1.outcome == 'failure' && steps.deploy2.outcome == 'failure'
continue-on-error: true
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
- name: Require Pages deployment success
if: steps.deploy1.outcome != 'success' && steps.deploy2.outcome != 'success' && steps.deploy3.outcome != 'success'
shell: bash
run: |
echo "::error::GitHub Pages deployment failed after 3 attempts"
exit 1
verify-deployed:
needs: [changes, deploy]
if: >-
always() &&
needs.changes.outputs.deployment-reuse != 'true' &&
needs.deploy.result == 'success' &&
(github.event_name == 'push' ||
(github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main'))
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
# Build a sitemap URL that is robust against future
# actions/deploy-pages versions changing whether `page_url`
# carries a trailing slash. The current contract has one, but
# normalising explicitly costs nothing and removes the implicit
# dependency.
- name: Resolve sitemap URL
id: sitemap
shell: bash
env:
PAGE_URL: ${{ needs.deploy.outputs.page-url }}
run: |
set -euo pipefail
echo "url=${PAGE_URL%/}/sitemap.xml" >> "$GITHUB_OUTPUT"
- name: Verify deployed docs links
uses: ./.github/actions/check-deployed-docs
with:
sitemap-url: ${{ steps.sitemap.outputs.url }}
edit-url: ${{ env.JACKIN_REPO_EDIT_URL }}
blob-url: ${{ env.JACKIN_REPO_BLOB_URL }}
github-token: ${{ github.token }}
external-links: "false"
check-deployed:
# Schedule verifies the live deployed site against the main-branch source.
# Non-main workflow_dispatch runs validate the branch's source/build/link
# surface only; remapping the deployed main site against a feature checkout
# produces false missing-file failures after source moves.
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Verify deployed docs links
uses: ./.github/actions/check-deployed-docs
with:
sitemap-url: ${{ env.DOCS_SITE_URL }}/sitemap.xml
edit-url: ${{ env.JACKIN_REPO_EDIT_URL }}
blob-url: ${{ env.JACKIN_REPO_BLOB_URL }}
github-token: ${{ github.token }}
# Skip on schedule because schedule runs only `check-deployed` and a
# one-job aggregator on schedule has no value.
docs-required:
if: always() && github.event_name != 'schedule'
needs: [changes, repo-link-check, docs-link-check, prepare-codebook, spell-check-docs, spell-check-source, deploy, verify-deployed, check-deployed]
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/aggregate-needs
with:
needs-json: ${{ toJSON(needs) }}
workflow-label: docs
- name: Audit every Docs job's performance
if: always()
env:
EXPECT_CLEAN: ${{ needs.changes.outputs.result-reuse == 'true' }}
GH_TOKEN: ${{ github.token }}
WORKFLOW_LABEL: Docs
run: scripts/ci/audit-workflow-performance.sh
- name: Stage input-identical successful Docs result
if: >-
needs.changes.outputs.result-reuse != 'true' &&
(github.ref == 'refs/heads/main' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
run: printf '%s\n' "source-sha=${GITHUB_SHA}" > docs-result.txt
- name: Publish input-identical successful Docs result
if: >-
needs.changes.outputs.result-reuse != 'true' &&
(github.ref == 'refs/heads/main' ||
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository))
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ needs.changes.outputs.result-name }}
path: docs-result.txt
compression-level: 0
retention-days: 7