chore(deps): bump DavidAnson/markdownlint-cli2-action from 23.2.0 to 24.1.0 #266
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
| name: Required Checks | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| merge_group: | |
| types: [checks_requested] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: required-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| name: lint | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Install shellcheck | |
| run: sudo apt-get install -y shellcheck | |
| - name: Shellcheck on all shell scripts | |
| run: find . -name "*.sh" | xargs shellcheck | |
| - name: Install yamllint | |
| run: pip install yamllint | |
| - name: yamllint on all YAML files | |
| run: yamllint -c .yamllint.yaml . | |
| - name: Check for Python files | |
| id: py-check | |
| run: | | |
| count=$(find . -name "*.py" -not -path "./.git/*" | wc -l) | |
| echo "count=${count}" >> "$GITHUB_OUTPUT" | |
| - name: Install mypy and run type check | |
| if: steps.py-check.outputs.count != '0' | |
| run: pip install mypy && mypy --ignore-missing-imports . | |
| - name: No Python files — emit notice and validate syntax | |
| if: steps.py-check.outputs.count == '0' | |
| run: | | |
| echo "::notice::No Python files found; skipping mypy" | |
| find . -name "*.py" -not -path "./.git/*" | xargs -r python -m py_compile | |
| echo "Python compile check complete (0 files)" | |
| - name: Set up Node.js (for tsc) | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: dagger/package-lock.json | |
| - name: Install dagger TypeScript deps | |
| run: cd dagger && npm ci | |
| - name: TypeScript type check (tsc --noEmit) | |
| run: cd dagger && npx tsc --noEmit | |
| - name: Verify issue #92 invariants | |
| # Static-source regression guard moved from ci.yml/lint-scripts | |
| # (closes #94 F1). See scripts/verify-issue-92-invariants.sh | |
| # for the three invariants enforced. | |
| run: bash scripts/verify-issue-92-invariants.sh | |
| forbid-suppressions: | |
| name: forbid-suppressions | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: "Reject silent-failure workaround in shell/YAML/Dockerfile/justfile/HCL" | |
| run: | | |
| # Matches the forbidden idiom at end of line or before a trailing | |
| # comment. See docs/runbooks/no-silent-failures.md (ported from | |
| # HomericIntelligence/Odysseus#280). | |
| set -euo pipefail | |
| mapfile -t files < <(git ls-files \ | |
| -- \ | |
| '*.sh' '*.bash' '*.yml' '*.yaml' '*.hcl' \ | |
| 'Dockerfile*' '**/Dockerfile*' \ | |
| 'justfile' '**/justfile' 'Justfile' '**/Justfile') | |
| # Skip the runbook (documents the rule and quotes the forbidden idiom) | |
| # and this workflow file itself (heredoc would otherwise self-match). | |
| declare -a scan_files=() | |
| for f in "${files[@]}"; do | |
| case "$f" in | |
| docs/runbooks/no-silent-failures.md) continue ;; | |
| .github/workflows/_required.yml) continue ;; | |
| esac | |
| scan_files+=("$f") | |
| done | |
| if [ "${#scan_files[@]}" -eq 0 ]; then | |
| echo "No files to scan" | |
| exit 0 | |
| fi | |
| if grep -nE '\|\|[[:space:]]*true([[:space:]]*$|[[:space:]]+#)' "${scan_files[@]}"; then | |
| echo "" | |
| echo '::error::Found silent-failure workarounds above. Refactor per docs/runbooks/no-silent-failures.md.' | |
| exit 1 | |
| fi | |
| echo 'OK: no silent-failure workarounds found' | |
| - name: "Reject continue-on-error workflow opt-out" | |
| run: | | |
| set -euo pipefail | |
| mapfile -t files < <(git ls-files -- '.github/workflows/*.yml' '.github/workflows/*.yaml') | |
| if [ "${#files[@]}" -eq 0 ]; then | |
| echo "No workflow files" | |
| exit 0 | |
| fi | |
| if grep -nE '^[[:space:]]*continue-on-error:[[:space:]]*true[[:space:]]*$' "${files[@]}"; then | |
| echo "" | |
| echo '::error::Found "continue-on-error: true" above. Fix the root cause per docs/runbooks/no-silent-failures.md.' | |
| exit 1 | |
| fi | |
| echo 'OK: no "continue-on-error: true" found' | |
| unit-tests: | |
| name: unit-tests | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup pixi | |
| uses: prefix-dev/setup-pixi@a09b6247153796b190642a2b53fac4241043cf6f # v0.10.0 | |
| with: | |
| pixi-version: v0.69.0 | |
| cache: true | |
| - name: Bootstrap proteus | |
| run: pixi run bootstrap-proteus | |
| - name: Run pytest | |
| run: pixi run pytest tests/unit -v | |
| - name: Run pipeline-config unit tests | |
| run: pixi run pytest tests/test_loader.py tests/test_topology.py tests/test_handlers.py -q | |
| - name: Install jq | |
| run: sudo apt-get install -y jq | |
| - name: Test dispatch-apply.sh payload construction | |
| run: ./scripts/test/test-dispatch-apply.sh | |
| - name: Test check-symlinks.sh broken-symlink detection | |
| run: bash tests/unit/check-symlinks.test.sh | |
| - name: Test promote-image.sh argument validation | |
| run: bash tests/unit/promote-image.test.sh | |
| - name: Run required-checks ruleset regression test | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bash tests/test-required-checks-ruleset.sh | |
| integration-tests: | |
| name: integration-tests | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup pixi | |
| uses: prefix-dev/setup-pixi@a09b6247153796b190642a2b53fac4241043cf6f # v0.10.0 | |
| with: | |
| pixi-version: v0.69.0 | |
| cache: true | |
| - name: Bootstrap proteus | |
| run: pixi run bootstrap-proteus | |
| - name: Schema-in-sync check | |
| run: pixi run pytest tests/unit/test_schema_in_sync.py -v | |
| - name: Pipeline-config dry-run (drift guard) | |
| run: | | |
| for f in configs/pipelines/*.yaml; do | |
| svc=$(basename "$f" .yaml) | |
| pixi run python -m proteus run "$f" --service "$svc" --dry-run | |
| done | |
| - name: Run pipeline-config integration tests | |
| run: pixi run pytest tests/test_main_integration.py -q | |
| - name: Validate pipeline configs against pipeline schema | |
| run: pixi run python -m proteus.pipeline validate 'configs/pipelines/*.yaml' | |
| - name: Assert jq present (required by dispatch-apply DLQ) | |
| run: command -v jq && jq --version | |
| - name: Run merge-queue activation fail-safe tests | |
| run: bash tests/merge-queue-activation.test.sh | |
| - name: Test dispatch-apply host validation (fail-closed contract) | |
| run: bash tests/dispatch-apply.test.sh | |
| - name: Run dispatch-apply retry/DLQ tests | |
| run: bash tests/dispatch-apply-retry.test.sh | |
| - name: Run remediation-plan sync test | |
| run: bash tests/remediation-plan-sync.test.sh | |
| - name: Run remediation-plan checkbox regression test | |
| run: bash tests/remediation-plan-checkboxes.test.sh | |
| security-dependency-scan: | |
| name: security/dependency-scan | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Trivy filesystem scan | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: fs | |
| scan-ref: . | |
| exit-code: '1' | |
| severity: CRITICAL,HIGH | |
| security-secrets-scan: | |
| name: security/secrets-scan | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Gitleaks | |
| run: | | |
| GITLEAKS_VERSION=8.30.1 | |
| OS=$(uname -s | tr '[:upper:]' '[:lower:]') | |
| ARCH=$(uname -m | sed 's/x86_64/x64/;s/aarch64/arm64/') | |
| curl -sSfL \ | |
| "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_${OS}_${ARCH}.tar.gz" \ | |
| | tar -xz -C /usr/local/bin gitleaks | |
| gitleaks version | |
| - name: Run Gitleaks | |
| run: | | |
| # Gitleaks exits 1 on any finding (default). The SARIF upload step | |
| # below uses `if: always()` so the report is preserved even when | |
| # this step fails. See docs/runbooks/no-silent-failures.md. | |
| set -euo pipefail | |
| if [ -f .gitleaks.toml ]; then | |
| gitleaks detect --source . --config .gitleaks.toml \ | |
| --report-format sarif --report-path gitleaks.sarif | |
| else | |
| gitleaks detect --source . \ | |
| --report-format sarif --report-path gitleaks.sarif | |
| fi | |
| - name: Upload Gitleaks SARIF | |
| if: always() && hashFiles('gitleaks.sarif') != '' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: gitleaks-report | |
| path: gitleaks.sarif | |
| retention-days: 90 | |
| - name: Enforce Gitleaks on PRs (fail on findings) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| # PR-only enforcement; main pushes stay advisory per | |
| # docs/runbooks/no-silent-failures.md Bucket E and issue #86. | |
| if [ -f .gitleaks.toml ]; then | |
| gitleaks detect --source . --config .gitleaks.toml --exit-code 1 | |
| else | |
| gitleaks detect --source . --exit-code 1 | |
| fi | |
| security-npm-audit: | |
| name: security/npm-audit | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: dagger/package-lock.json | |
| - name: Install dependencies (locked) | |
| run: cd dagger && npm ci | |
| - name: npm audit (production, high+) | |
| run: cd dagger && npm audit --omit=dev --audit-level=high | |
| build: | |
| name: build | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Validate shell script shebangs | |
| run: | | |
| count=$(find . -name "*.sh" | xargs head -1 | grep -c "#!/" || true) | |
| echo "Found ${count} shebang line(s) across shell scripts" | |
| - name: Bash syntax check on all shell scripts | |
| run: find . -name "*.sh" | xargs -I{} bash -n {} | |
| schema-validation: | |
| name: schema-validation | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Install check-jsonschema | |
| run: pip install check-jsonschema | |
| - name: Validate GitHub workflow files against schema | |
| run: | | |
| # Validation is advisory: schemastore is sometimes stale relative to | |
| # new Actions syntax. Emit a workflow warning on mismatch but do not | |
| # fail the job. Explicit `if`-guard replaces the prior | |
| # `continue-on-error: true` (Bucket E, docs/runbooks/no-silent-failures.md). | |
| set -euo pipefail | |
| if find .github/workflows -name "*.yml" | \ | |
| xargs check-jsonschema \ | |
| --schemafile https://json.schemastore.org/github-workflow | |
| then | |
| echo "OK: workflow files match schemastore schema" | |
| else | |
| echo "::warning::Workflow schema validation reported issues (advisory)." | |
| fi | |
| deps-version-sync: | |
| name: deps/version-sync | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Report pinned versions in shell scripts (informational) | |
| run: | | |
| echo "=== Pinned version strings in shell scripts ===" | |
| grep -rh "version=" . --include="*.sh" | sort -u || echo "(none found)" | |
| exit 0 | |
| - name: Validate pyproject.toml version if present | |
| run: | | |
| if [ -f pyproject.toml ]; then | |
| python -c " | |
| import tomllib, pathlib | |
| data = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) | |
| ver = data.get('project', {}).get('version') or data.get('tool', {}).get('poetry', {}).get('version') | |
| print(f'pyproject.toml version: {ver}') | |
| " | |
| else | |
| echo "No pyproject.toml found — skipping version check" | |
| fi | |
| markdownlint: | |
| name: markdownlint | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| needs: lint | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Run markdownlint-cli2 | |
| uses: DavidAnson/markdownlint-cli2-action@6bf21b07787794f89a243495939cd651942aeabe # v20.0.0 | |
| with: | |
| globs: "**/*.md | |
| !.claude/**" | |
| config: ".markdownlint.yaml" | |
| pixi-check: | |
| name: pixi-check | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| needs: lint | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Skip if no pixi.toml | |
| id: detect | |
| run: | | |
| if [ ! -f pixi.toml ]; then | |
| echo "::notice::No pixi.toml in repo, skipping pixi-check" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Setup pixi | |
| if: steps.detect.outputs.skip == 'false' | |
| uses: prefix-dev/setup-pixi@a09b6247153796b190642a2b53fac4241043cf6f # v0.10.0 | |
| with: | |
| pixi-version: v0.69.0 | |
| cache: true | |
| - name: pixi install (locked) | |
| if: steps.detect.outputs.skip == 'false' | |
| run: | | |
| if [ -f pixi.lock ]; then | |
| pixi install --locked | |
| else | |
| echo "::warning::pixi.toml present but pixi.lock missing — running unlocked" | |
| pixi install | |
| fi | |
| justfile-check: | |
| name: justfile-check | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| needs: lint | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Skip if no justfile | |
| id: detect | |
| run: | | |
| if [ ! -f justfile ] && [ ! -f Justfile ]; then | |
| echo "::notice::No justfile in repo, skipping justfile-check" | |
| echo "skip=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "skip=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install just | |
| if: steps.detect.outputs.skip == 'false' | |
| uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4.0.0 | |
| with: | |
| just-version: "1.36.0" | |
| - name: Validate justfile | |
| if: steps.detect.outputs.skip == 'false' | |
| run: | | |
| just --evaluate >/dev/null | |
| just --list >/dev/null | |
| symlink-check: | |
| name: symlink-check | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 3 | |
| needs: lint | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Run symlink check | |
| run: bash scripts/check-symlinks.sh | |
| branch-protection-test: | |
| name: branch-protection-test | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup pixi | |
| uses: prefix-dev/setup-pixi@a09b6247153796b190642a2b53fac4241043cf6f # v0.10.0 | |
| with: | |
| pixi-version: v0.69.0 | |
| - name: Validate ruleset JSON | |
| run: pixi run jq . .github/branch-protection.main.json >/dev/null | |
| - name: Verify every context maps to a real workflow job name | |
| run: bash scripts/verify-context-names.sh | |
| - name: Run offline branch-protection verifier test | |
| run: pixi run test-branch-protection | |
| version-consistency: | |
| name: version-consistency | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Run version-consistency tests (issue #101) | |
| run: bash tests/version-consistency.test.sh | |
| # Canonical aggregate gate for the test category (Odysseus CI naming | |
| # convention, docs/ci-naming-convention.md). Emits the canonical check-run | |
| # `test` that the Ecosystem CI Status board's test column targets. The split | |
| # suites (unit-tests / integration-tests / branch-protection-test) are kept | |
| # as their own check-runs; this job just succeeds once they all pass. | |
| test: | |
| name: test | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 5 | |
| needs: [unit-tests, integration-tests, branch-protection-test] | |
| steps: | |
| - name: All test suites passed | |
| run: | | |
| echo "OK: unit-tests, integration-tests, branch-protection-test all green" | |
| # Canonical `package` gate (Odysseus CI naming convention). Builds the | |
| # distributable for the installable `proteus` Python CLI (pyproject.toml | |
| # declares a setuptools build-backend and a `proteus` console script). | |
| package: | |
| name: package | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: '3.11' | |
| - name: Install build frontend | |
| run: pip install build | |
| - name: Build sdist and wheel | |
| run: python -m build --sdist --wheel --outdir dist/ | |
| - name: Verify distributable artifacts exist | |
| run: | | |
| set -euo pipefail | |
| ls -l dist/ | |
| test -n "$(ls dist/proteus-*.tar.gz 2>/dev/null)" || { | |
| echo "::error::No sdist produced under dist/"; exit 1; } | |
| test -n "$(ls dist/proteus-*-py3-none-any.whl 2>/dev/null)" || { | |
| echo "::error::No wheel produced under dist/"; exit 1; } | |
| echo "OK: sdist and wheel built" | |
| - name: Upload distributable artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: proteus-dist | |
| path: dist/ | |
| retention-days: 7 | |
| # Canonical `install` gate (Odysseus CI naming convention). Install smoke | |
| # test: pip-installs the built wheel into a clean virtualenv and exercises | |
| # the `proteus` console-script entry point declared in pyproject.toml. | |
| install: | |
| name: install | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| needs: package | |
| steps: | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: '3.11' | |
| - name: Download distributable artifacts | |
| uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: proteus-dist | |
| path: dist/ | |
| - name: Install wheel into a clean virtualenv | |
| run: | | |
| set -euo pipefail | |
| python -m venv /tmp/proteus-venv | |
| # shellcheck disable=SC1091 | |
| . /tmp/proteus-venv/bin/activate | |
| wheel="$(ls dist/proteus-*-py3-none-any.whl)" | |
| pip install "$wheel" | |
| echo "Installed: $wheel" | |
| - name: Run installed CLI entry point (smoke test) | |
| run: | | |
| set -euo pipefail | |
| # shellcheck disable=SC1091 | |
| . /tmp/proteus-venv/bin/activate | |
| # The `proteus` console script is the installed package's public | |
| # surface. `--help` exits 0 only if the entry point resolves and | |
| # argparse builds cleanly. | |
| proteus --help | |
| # `validate --help` exercises the validate subcommand wiring. | |
| proteus validate --help |