name: Hadolint Dockerfile Linting on: pull_request: paths: - 'Dockerfile' - '.hadolint.yaml' workflow_dispatch: workflow_call: # Called by release-gate.yml schedule: # Run weekly on Tuesday at 9 AM UTC - cron: '0 9 * * 2' # No concurrency group — intentionally omitted. # This workflow triggers on both pull_request and workflow_call (from # ci-gate.yml / release-gate.yml). A shared concurrency key would cause # direct PR runs and workflow_call runs to cancel each other mid-flight. # See #3554 (reverted in #3599) for context. permissions: {} # Minimal top-level for OSSF Scorecard Token-Permissions jobs: hadolint: name: Hadolint Dockerfile Analysis runs-on: ubuntu-latest permissions: contents: read security-events: write steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Run Hadolint on Dockerfile uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 with: dockerfile: Dockerfile format: sarif output-file: hadolint.sarif no-fail: false verbose: true - name: Upload Hadolint results to GitHub Security uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3 if: always() with: sarif_file: hadolint.sarif category: hadolint - name: Upload Hadolint results as artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: always() with: name: hadolint-results path: hadolint.sarif retention-days: 7 # Reduced for security - name: Run Hadolint with detailed output uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0 if: always() with: dockerfile: Dockerfile format: tty no-fail: false continue-on-error: false - name: Display Hadolint summary if: always() run: | { echo "## Hadolint Dockerfile Analysis Summary" echo "" echo "✅ Hadolint analysis completed" echo "" echo "### What is Hadolint?" echo "Hadolint is a Dockerfile linter that checks for best practices and common mistakes:" echo "" echo "#### Security Checks" echo "- 🔒 Running as root user" echo "- 🔑 Using latest tag" echo "- 📦 Missing version pinning" echo "- ⚠️ Exposed secrets in build args" echo "" echo "#### Best Practices" echo "- 🎯 Layer optimization" echo "- 🗑️ Cleaning package manager cache" echo "- 📝 Using COPY instead of ADD" echo "- 🔧 Proper WORKDIR usage" echo "- 💾 Efficient layer caching" echo "" echo "#### Build Efficiency" echo "- 🚀 Multi-stage build opportunities" echo "- 📦 Unnecessary packages" echo "- 🔄 Combining RUN commands" echo "" echo "📊 **Results:**" echo "- Detailed results uploaded to GitHub Security tab" echo "- SARIF file available in artifacts" echo "" echo "🔗 **Links:**" echo "- [Security Tab](https://github.com/${{ github.repository }}/security/code-scanning)" echo "- [Hadolint Rules](https://github.com/hadolint/hadolint#rules)" } >> "$GITHUB_STEP_SUMMARY"