Files
docker_practice/.github/workflows/ci.yaml
T
yeasy 21e43e1927 ci: stop && from swallowing a check_project_rules failure
The step ran `check_project_rules.py && check_emphasis.py` with more
commands on following lines. Under `bash -e` the left operand of `&&`
is an exempt context, so a rules failure did NOT abort the step: it
short-circuited past check_emphasis.py, execution continued to the next
line, and the step exited with that last command's status -- green.

Demonstrated:
  bash -e -c 'false_check && emphasis
              next_cmd'          -> exit 0   (failure swallowed)
  bash -e -c 'false_check
              emphasis
              next_cmd'          -> exit 1   (correctly blocks)

So the repo's main content gate could fail while CI stayed green, and
today's new CJK emphasis gate was skipped entirely whenever it did.
Splitting the line restores fail-fast for both.

Swept all 14 repos: only this one and the other CI whose && line is
followed by further commands were affected; the 12 where the && list is
the last line of its run block already exit non-zero and are unchanged.

Verified: YAML parses, both checkers pass, repo test suite unchanged.
2026-07-24 19:05:25 -07:00

125 lines
5.1 KiB
Go

name: CI
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
permissions: {}
jobs:
build:
permissions:
contents: read
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install locked Node dependencies
env:
PUPPETEER_SKIP_DOWNLOAD: "true"
run: npm ci
- name: Install canonical-example validators
env:
KUBECONFORM_VERSION: "0.8.0"
KUBECONFORM_SHA256: "9bc2bffbf71f261128533edaf912153948b7ff238f9a531ae6d34466ec287883"
ACTIONLINT_VERSION: "1.7.12"
ACTIONLINT_SHA256: "8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8"
run: |
mkdir -p "$RUNNER_TEMP/bin"
kube_archive="$RUNNER_TEMP/kubeconform.tar.gz"
curl -fsSL --retry 3 \
"https://github.com/yannh/kubeconform/releases/download/v${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \
-o "$kube_archive"
echo "${KUBECONFORM_SHA256} $kube_archive" | sha256sum -c -
tar xzf "$kube_archive" -C "$RUNNER_TEMP/bin" kubeconform
actionlint_archive="$RUNNER_TEMP/actionlint.tar.gz"
curl -fsSL --retry 3 \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" \
-o "$actionlint_archive"
echo "${ACTIONLINT_SHA256} $actionlint_archive" | sha256sum -c -
tar xzf "$actionlint_archive" -C "$RUNNER_TEMP/bin" actionlint
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- name: Check project rules, metadata, and canonical examples
run: |
python3 check_project_rules.py
python3 check_emphasis.py
npm test
python3 tools/test_examples.py --require-tools
- name: Install Chromium
uses: browser-actions/setup-chrome@2e1d749697dd1612b833dba4a722266286fbefcd # v2.1.2
with:
chrome-version: stable
- name: Install CJK fonts and PDF inspection tools
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra poppler-utils
- name: Resolve latest mdPress release
run: |
url="$(curl -fsSL --retry 3 -o /dev/null -w '%{url_effective}' https://github.com/yeasy/mdPress/releases/latest)"
version="${url##*/v}"
test -n "$version" || { echo "could not resolve latest mdPress release"; exit 1; }
echo "MDPRESS_VERSION=$version" >> "$GITHUB_ENV"
echo "resolved mdPress $version"
- name: Install mdPress (checksum-verified)
run: |
archive="$RUNNER_TEMP/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"
curl -fsSL --retry 3 \
"https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" \
-o "$archive"
expected="$(curl -fsSL --retry 3 "https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/checksums.txt" \
| awk -v f="mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" '$2==f {print $1}')"
test -n "$expected" || { echo "no published checksum for mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"; exit 1; }
echo "${expected} $archive" | sha256sum -c -
tar xzf "$archive" -C "$RUNNER_TEMP" mdpress
mkdir -p "$RUNNER_TEMP/bin"
install -m 0755 "$RUNNER_TEMP/mdpress" "$RUNNER_TEMP/bin/mdpress"
echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH"
- name: Prepare PDF sources
run: python3 tools/prepare_pdf_sources.py --book-dir . --out "$RUNNER_TEMP/docker_practice-pdf-src"
- name: Build PDF
working-directory: ${{ runner.temp }}/docker_practice-pdf-src
run: |
# mdPress PDF generation drives headless Chrome, which intermittently dies with
# "websocket url timeout reached" + dbus errors. Retry the build, not the whole job.
mdpress() { local a; for a in 1 2 3; do command mdpress "$@" && return 0;
echo "::warning::mdpress attempt $a failed; retrying in 10s"; sleep 10; done; return 1; }
mkdir -p "$GITHUB_WORKSPACE/dist"
mdpress build --format pdf --output "$GITHUB_WORKSPACE/dist/docker_practice.pdf"
- name: Build site
run: npm run build
- name: Verify build artifacts
run: |
title=$(python3 -c 'import json; print(json.load(open("book.json", encoding="utf-8"))["title"])')
python3 tools/verify_artifacts.py \
--title "$title" \
--pdf dist/docker_practice.pdf \
--site _site \
--checksums dist/SHA256SUMS
(cd dist && sha256sum -c SHA256SUMS)
- name: Upload verified PDF
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker_practice-pdf
path: |
dist/docker_practice.pdf
dist/SHA256SUMS
if-no-files-found: error