Skip to content

CI: Harden workflows (strict bash + fail-fast gating) - #17

Merged
johnjaysonlpz merged 3 commits into
mainfrom
ci/harden-workflows
Feb 16, 2026
Merged

johnjaysonlpz merged 3 commits into
mainfrom
ci/harden-workflows

Conversation

@johnjaysonlpz

@johnjaysonlpz johnjaysonlpz commented Feb 16, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR hardens our CI and reusable security workflows by standardizing Bash execution and enabling strict error handling (set -Eeuo pipefail). It also improves supply-chain safety by pinning workflow action SHAs, fixes Python caching behavior, and aligns local CI tooling with the same dependency-lock guarantees used in CI.

Highlights

  • Standardized defaults.run.shell: bash where appropriate to avoid shell drift.
  • Added set -Eeuo pipefail to script steps across CI + reusable security workflows for fail-fast behavior.
  • Pinned GitHub Actions to immutable commit SHAs across workflows for stronger supply-chain integrity.
  • Fixed Python caching to correctly include lockfiles and avoid stale/incorrect dependency reuse.
  • Aligned .ci-local.sh with CI by enforcing/locking requirements.test.lock (same contract as CI).

What changed

Control plane (Docker / Compose / Observability / CI)

  • CI workflow (.github/workflows/ci.yaml):
    • Added defaults.run.shell: bash to jobs that run Bash snippets.
    • Added set -Eeuo pipefail to relevant run: scripts (changes detection, policy enforcement, build metadata, gating).
    • Ensured actions are pinned by SHA (checkout/setup/cache/upload/etc.) for deterministic execution.
  • Reusable security workflows:
    • _trivy_repo.yaml: standardized Bash defaults + strict mode in scripted steps.
    • _trivy_image.yaml: standardized Bash defaults + strict mode in scan-ref compute + gating scripts.
    • _govulncheck.yaml: standardized Bash defaults + strict mode for install/PATH + scan + gating.
    • _pip_audit.yaml: standardized Bash defaults + strict mode for venv/bootstrap + scan + gating.
    • _dependency_check.yaml: standardized Bash defaults + strict mode for epoch compute + scan + gating.
  • Tooling:
    • load-tool-versions composite action:
      • Reads .ci-tool-versions.sh from $GITHUB_WORKSPACE.
      • Maintains strict allowlist + per-key regex validation before writing to GITHUB_ENV.
  • Local CI parity:
    • Updated .ci-local.sh to include the same lock behavior for requirements.test.lock as CI (fail if drift / enforce regeneration + diff behavior, depending on your implementation).

Services (Go / Java / Python)

  • Python / Django:
    • Fixed dependency caching keys/paths to include the correct lockfiles (and avoid cache collisions/stale environments).
    • Ensures requirements.lock + requirements.test.lock are treated as the source of truth consistently (CI + local parity).

Docs / Tooling

  • None beyond tooling hardening above.

Breaking changes / Migration notes

None.

How to test

Local / Integration

# CI lint / quick validation (optional)
yamllint .github/workflows/*.yaml .github/actions/*/action.yml  # if you use yamllint locally

# Simulate tool version loading locally (optional)
bash -c "set -Eeuo pipefail; file='.ci-tool-versions.sh'; test -f \"$file\"; cat \"$file\""

Verify

  • Open a PR that touches:
    • a service directory (golang-gin/**, java-springboot/**, python-django/**) and confirm only relevant jobs run.
    • a “protected CI control file” and confirm the policy job blocks non-maintainers.
  • Confirm action pinning is in place:
    • workflow steps reference actions by full commit SHA (not floating tags).
  • Confirm Python caching behaves correctly:
    • cache key changes when either requirements.lock or requirements.test.lock changes.
    • CI does not reuse stale .venv-ci state across lock changes.
  • Confirm security workflows still behave as intended:
    • Trivy repo/image jobs upload artifacts/SARIF even when findings exist (because scan steps can be continue-on-error).
    • The explicit Gate - fail if ... found issues step fails the job when gating is enabled.
      Confirm .ci-tool-versions.sh validation fails closed if:
    • an unexpected key is added, or
    • a value doesn’t match the expected regex.
      Confirm local tooling parity:
    • .ci-local.sh enforces/updates requirements.test.lock consistently with CI expectations.

Artifacts

  • N/A

Notes

  • Strict mode (-u) can surface previously hidden issues if scripts relied on unset variables. This is intentional to avoid silent misconfigurations.
  • Cleanup steps that intentionally tolerate failure still use set +e where needed (e.g., Docker Hub temp tag cleanup).

References

  • N/A (internal CI hardening / workflow reliability improvement)

@johnjaysonlpz johnjaysonlpz self-assigned this Feb 16, 2026
@johnjaysonlpz johnjaysonlpz added enhancement New feature or request refactor labels Feb 16, 2026
@johnjaysonlpz johnjaysonlpz changed the title Ci/harden workflows CI: Harden reusable security workflows (strict bash) Feb 16, 2026
@johnjaysonlpz johnjaysonlpz changed the title CI: Harden reusable security workflows (strict bash) CI: Harden workflows (strict bash + fail-fast gating) Feb 16, 2026
@johnjaysonlpz
johnjaysonlpz merged commit d11fa5d into main Feb 16, 2026
9 checks passed
@johnjaysonlpz
johnjaysonlpz deleted the ci/harden-workflows branch February 16, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request refactor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant