feat: add nightly branch workflow
This commit is contained in:
@@ -15,6 +15,7 @@ Restore DoD to ✅ PASS by eliminating **all HIGH/CRITICAL** findings from:
|
||||
- Trivy results produced by **Security: Trivy Scan**
|
||||
|
||||
Hard constraints:
|
||||
|
||||
- Do **not** weaken gates (no suppressing findings unless a false-positive is proven and documented).
|
||||
- Prefer minimal, targeted changes.
|
||||
- Avoid adding new runtime dependencies.
|
||||
@@ -40,10 +41,12 @@ QA report note: Trivy filesystem scan may be picking up **workspace caches/artif
|
||||
## Step 0 — Trivy triage (required first)
|
||||
|
||||
Objective: Re-run the current Trivy task and determine whether HIGH/CRITICAL findings are attributable to:
|
||||
|
||||
- **Repo-tracked paths** (e.g., `backend/go.mod`, `backend/go.sum`, `Dockerfile`, `frontend/`, etc.), or
|
||||
- **Generated/cache paths** under the workspace (e.g., `.cache/`, `**/*.cover`, `codeql-db-*`, temporary build outputs).
|
||||
|
||||
Steps:
|
||||
|
||||
1. Run **Security: Trivy Scan**.
|
||||
2. For each HIGH/CRITICAL item, record the affected file path(s) reported by Trivy.
|
||||
3. Classify each finding:
|
||||
@@ -51,6 +54,7 @@ Steps:
|
||||
- **Scan-scope noise**: path is a workspace cache/artifact directory not intended as deliverable input.
|
||||
|
||||
Decision outcomes:
|
||||
|
||||
- If HIGH/CRITICAL are **repo-tracked / shipped** → remediate by upgrading only the affected components to Trivy’s fixed versions (see Workstreams C/D).
|
||||
- If HIGH/CRITICAL are **only cache/artifact paths** → treat as scan-scope noise and align Trivy scan scope to repo contents by excluding those directories (without disabling scanners or suppressing findings).
|
||||
|
||||
@@ -68,6 +72,7 @@ Implementation direction (minimal + CodeQL-friendly):
|
||||
4. Add unit tests that attempt CRLF injection in subject/from/to and assert the send/build path rejects it.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- CodeQL Go scan shows **0** `go/email-injection` findings.
|
||||
- Backend unit tests cover the rejection paths.
|
||||
|
||||
@@ -76,9 +81,11 @@ Acceptance criteria:
|
||||
Objective: Remove an “incomplete hostname regex” pattern flagged by CodeQL.
|
||||
|
||||
Preferred change:
|
||||
|
||||
- Replace hostname regex usage with an exact string match (or an anchored + escaped regex like `^link\.example\.com$`).
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- CodeQL JS scan shows **0** `js/incomplete-hostname-regexp` findings.
|
||||
|
||||
### Workstream C — Container / embedded binaries (DevOps): Fix Trivy image finding
|
||||
@@ -92,6 +99,7 @@ Implementation direction:
|
||||
3. If no suitable CrowdSec release is available, patch the build in the CrowdSec build stage similarly to the existing Caddy stage override (force `expr@1.17.7` before building).
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- Trivy image scan reports **0 HIGH/CRITICAL**.
|
||||
|
||||
### Workstream D — Go module upgrades (Backend_Dev + QA_Security): Fix Trivy repo scan findings
|
||||
@@ -101,13 +109,17 @@ Objective: Eliminate Trivy filesystem-scan HIGH/CRITICAL findings without over-u
|
||||
Implementation direction (conditional; driven by Step 0 triage):
|
||||
|
||||
1. If Trivy attributes HIGH/CRITICAL to `backend/go.mod` / `backend/go.sum` **or** to the built `app/charon` binary:
|
||||
- Bump **only the specific Go modules Trivy flags** to Trivy’s fixed versions.
|
||||
- Run `go mod tidy` and ensure builds/tests stay green.
|
||||
2. If Trivy attributes HIGH/CRITICAL **only** to workspace caches / generated artifacts (e.g., `.cache/go/pkg/mod/...`):
|
||||
- Treat as scan-scope noise and align Trivy’s filesystem scan scope to repo-tracked content by excluding those directories.
|
||||
- This is **not** gate weakening: scanners stay enabled and the project must still achieve **0 HIGH/CRITICAL** in Trivy outputs.
|
||||
|
||||
- Bump **only the specific Go modules Trivy flags** to Trivy’s fixed versions.
|
||||
- Run `go mod tidy` and ensure builds/tests stay green.
|
||||
|
||||
1. If Trivy attributes HIGH/CRITICAL **only** to workspace caches / generated artifacts (e.g., `.cache/go/pkg/mod/...`):
|
||||
|
||||
- Treat as scan-scope noise and align Trivy’s filesystem scan scope to repo-tracked content by excluding those directories.
|
||||
- This is **not** gate weakening: scanners stay enabled and the project must still achieve **0 HIGH/CRITICAL** in Trivy outputs.
|
||||
|
||||
Acceptance criteria:
|
||||
|
||||
- Trivy scan reports **0 HIGH/CRITICAL**.
|
||||
|
||||
## Validation (VS Code tasks)
|
||||
@@ -122,14 +134,14 @@ Run tasks in this order (only run frontend ones if Workstream B changes anything
|
||||
|
||||
If any changes are made to `Dockerfile` / CrowdSec build stage:
|
||||
|
||||
6. **Build & Run: Local Docker Image No-Cache** (recommended)
|
||||
7. **Security: Trivy Scan** (re-verify image scan after rebuild)
|
||||
1. **Build & Run: Local Docker Image No-Cache** (recommended)
|
||||
2. **Security: Trivy Scan** (re-verify image scan after rebuild)
|
||||
|
||||
If `frontend/` changes are made:
|
||||
|
||||
6. **Lint: TypeScript Check**
|
||||
7. **Test: Frontend with Coverage**
|
||||
8. **Lint: Frontend**
|
||||
1. **Lint: TypeScript Check**
|
||||
2. **Test: Frontend with Coverage**
|
||||
3. **Lint: Frontend**
|
||||
|
||||
## Handoff checklist
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
## Executive Summary
|
||||
|
||||
GitHub Advanced Security is reporting that 2 workflow configurations from `refs/heads/main` are missing in the current PR branch (`feature/beta-release`):
|
||||
|
||||
1. `.github/workflows/security-weekly-rebuild.yml:security-rebuild`
|
||||
2. `.github/workflows/docker-publish.yml:build-and-push`
|
||||
|
||||
@@ -23,6 +24,7 @@ GitHub Advanced Security is reporting that 2 workflow configurations from `refs/
|
||||
### 1. File State Analysis
|
||||
|
||||
#### Current Branch (`feature/beta-release`)
|
||||
|
||||
```
|
||||
✅ .github/workflows/security-weekly-rebuild.yml EXISTS
|
||||
- Job name: security-rebuild
|
||||
@@ -42,6 +44,7 @@ GitHub Advanced Security is reporting that 2 workflow configurations from `refs/
|
||||
```
|
||||
|
||||
#### Main Branch (`refs/heads/main`)
|
||||
|
||||
```
|
||||
✅ .github/workflows/security-weekly-rebuild.yml EXISTS
|
||||
- Job name: security-rebuild
|
||||
@@ -67,6 +70,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
```
|
||||
|
||||
**Key Findings:**
|
||||
|
||||
- `docker-publish.yml` was deleted on **BOTH** main and feature/beta-release branches
|
||||
- `docker-build.yml` exists on **BOTH** branches with the **SAME** job name
|
||||
- The warning is a GitHub Advanced Security tracking artifact from when `docker-publish.yml` existed
|
||||
@@ -85,6 +89,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
| **Concurrency Control** | ✅ Yes | ✅ Yes (ENHANCED) |
|
||||
|
||||
**Improvement Analysis:** `docker-build.yml` is **MORE SECURE** than the deleted `docker-publish.yml`:
|
||||
|
||||
- Added SBOM generation (supply chain security)
|
||||
- Added SBOM attestation with cryptographic signing
|
||||
- Added CVE-2025-68156 verification for Caddy
|
||||
@@ -102,6 +107,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
| `docker-build.yml` | `trivy-pr-app-only` | ✅ Yes (app binary) | ❌ No | PR only |
|
||||
|
||||
**Coverage Assessment:**
|
||||
|
||||
- Weekly security rebuilds: ✅ ACTIVE
|
||||
- Per-commit scanning: ✅ ACTIVE
|
||||
- PR-specific scanning: ✅ ACTIVE
|
||||
@@ -117,6 +123,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
**Symptom:** GitHub Advanced Security tracks workflow configurations by **filename + job name**. When a workflow file is deleted/renamed, GitHub Security's internal tracking doesn't automatically update the reference mapping.
|
||||
|
||||
**Root Cause Chain:**
|
||||
|
||||
1. `docker-publish.yml` existed on main branch (tracked as `docker-publish.yml:build-and-push`)
|
||||
2. Commit `f640524b` deleted `docker-publish.yml` and functionality was moved to `docker-build.yml`
|
||||
3. GitHub Security still has historical tracking data for `docker-publish.yml:build-and-push`
|
||||
@@ -124,6 +131,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
5. File not found → Warning generated
|
||||
|
||||
**Why This is a False Positive:**
|
||||
|
||||
- The job name `build-and-push` still exists in `docker-build.yml`
|
||||
- All Trivy scanning functionality is preserved (and enhanced)
|
||||
- Both branches have the same state (file deleted, functionality moved)
|
||||
@@ -132,6 +140,7 @@ Date: Sun Dec 21 15:11:25 2025 +0000
|
||||
### Why Was docker-publish.yml Deleted?
|
||||
|
||||
Based on git history and inspection:
|
||||
|
||||
1. **Consolidation:** Functionality was merged/improved in `docker-build.yml`
|
||||
2. **Enhancement:** `docker-build.yml` added SBOM, attestation, and CVE checks
|
||||
3. **Maintenance:** Reduced workflow file duplication
|
||||
@@ -142,15 +151,18 @@ Based on git history and inspection:
|
||||
## Resolution Strategy
|
||||
|
||||
### Option 1: Do Nothing (RECOMMENDED)
|
||||
|
||||
**Rationale:** This is a **false positive tracking issue**, not a functional security problem.
|
||||
|
||||
**Pros:**
|
||||
|
||||
- No code changes required
|
||||
- No risk of breaking existing functionality
|
||||
- Security coverage is complete and enhanced
|
||||
- Warning will eventually clear when GitHub Security updates its tracking
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Warning remains visible in GitHub Security UI
|
||||
- May confuse reviewers/auditors
|
||||
|
||||
@@ -159,19 +171,23 @@ Based on git history and inspection:
|
||||
---
|
||||
|
||||
### Option 2: Force GitHub Security to Update Tracking
|
||||
|
||||
**Approach:** Trigger a manual re-scan or workflow dispatch on main branch to refresh GitHub Security's workflow registry.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to Actions → `security-weekly-rebuild.yml`
|
||||
2. Click "Run workflow" → Run on main branch
|
||||
3. Wait for workflow completion
|
||||
4. Check if GitHub Security updates its tracking
|
||||
|
||||
**Pros:**
|
||||
|
||||
- May clear the warning faster
|
||||
- No code changes required
|
||||
|
||||
**Cons:**
|
||||
|
||||
- No guarantee GitHub Security will update tracking immediately
|
||||
- May need to wait for GitHub's internal cache/indexing to refresh
|
||||
- Uses CI/CD resources
|
||||
@@ -181,9 +197,11 @@ Based on git history and inspection:
|
||||
---
|
||||
|
||||
### Option 3: Re-create docker-publish.yml as a Wrapper (NOT RECOMMENDED)
|
||||
|
||||
**Approach:** Create a new `docker-publish.yml` that calls `docker-build.yml` via `workflow_call`.
|
||||
|
||||
**Example Implementation:**
|
||||
|
||||
```yaml
|
||||
# .github/workflows/docker-publish.yml
|
||||
name: Docker Publish (Deprecated - Use docker-build.yml)
|
||||
@@ -197,10 +215,12 @@ jobs:
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Satisfies GitHub Security's filename tracking
|
||||
- Maintains backward compatibility for any external references
|
||||
|
||||
**Cons:**
|
||||
|
||||
- ❌ Creates unnecessary file duplication
|
||||
- ❌ Adds maintenance burden
|
||||
- ❌ Confuses future developers (two files doing the same thing)
|
||||
@@ -212,21 +232,25 @@ jobs:
|
||||
---
|
||||
|
||||
### Option 4: Add Comprehensive Documentation
|
||||
|
||||
**Approach:** Document the workflow file rename/migration in repository documentation.
|
||||
|
||||
**Implementation:**
|
||||
|
||||
1. Update `CHANGELOG.md` with entry for docker-publish.yml removal
|
||||
2. Add section to `SECURITY.md` explaining current Trivy coverage
|
||||
3. Create `.github/workflows/README.md` documenting workflow structure
|
||||
4. Add comment to `docker-build.yml` explaining it replaced `docker-publish.yml`
|
||||
|
||||
**Pros:**
|
||||
|
||||
- ✅ Improves project documentation
|
||||
- ✅ Helps future maintainers understand the change
|
||||
- ✅ Provides audit trail for security reviews
|
||||
- ✅ No functional changes, zero risk
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Doesn't clear the GitHub Security warning
|
||||
- Requires documentation updates
|
||||
|
||||
@@ -237,11 +261,14 @@ jobs:
|
||||
## Recommended Action Plan
|
||||
|
||||
### Phase 1: Documentation (IMMEDIATE)
|
||||
|
||||
**Objective:** Create audit trail and improve project documentation.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
1. ✅ Create this plan document (`docs/plans/GITHUB_SECURITY_WARNING_RESOLUTION_PLAN.md`) ← DONE
|
||||
2. Add entry to `CHANGELOG.md`:
|
||||
|
||||
```markdown
|
||||
### Changed
|
||||
- Replaced `.github/workflows/docker-publish.yml` with `.github/workflows/docker-build.yml` for enhanced supply chain security
|
||||
@@ -249,7 +276,9 @@ jobs:
|
||||
- Added CVE-2025-68156 verification for Caddy
|
||||
- Job name `build-and-push` preserved for continuity
|
||||
```
|
||||
|
||||
3. Add section to `SECURITY.md`:
|
||||
|
||||
```markdown
|
||||
## Security Scanning Coverage
|
||||
|
||||
@@ -267,7 +296,9 @@ jobs:
|
||||
|
||||
All Trivy results are uploaded to the [Security tab](../../security/code-scanning).
|
||||
```
|
||||
|
||||
4. Add header comment to `docker-build.yml`:
|
||||
|
||||
```yaml
|
||||
# This workflow replaced docker-publish.yml on 2025-12-21
|
||||
# Enhancement: Added SBOM generation, attestation, and CVE verification
|
||||
@@ -281,13 +312,17 @@ jobs:
|
||||
---
|
||||
|
||||
### Phase 2: Verification (AFTER DOCUMENTATION)
|
||||
|
||||
**Objective:** Confirm that security scanning is functioning correctly.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
1. Verify `security-weekly-rebuild.yml` is scheduled correctly:
|
||||
|
||||
```bash
|
||||
git show main:.github/workflows/security-weekly-rebuild.yml | grep -A 5 "schedule:"
|
||||
```
|
||||
|
||||
2. Check recent workflow runs in GitHub Actions UI:
|
||||
- Verify `docker-build.yml` runs on push/PR
|
||||
- Verify `security-weekly-rebuild.yml` runs weekly
|
||||
@@ -298,6 +333,7 @@ jobs:
|
||||
- Check for any missed scans
|
||||
|
||||
**Success Criteria:**
|
||||
|
||||
- ✅ All workflows show successful runs
|
||||
- ✅ Trivy SARIF results appear in Security tab
|
||||
- ✅ No scan failures in last 30 days
|
||||
@@ -310,14 +346,17 @@ jobs:
|
||||
---
|
||||
|
||||
### Phase 3: Monitor (ONGOING)
|
||||
|
||||
**Objective:** Track if GitHub Security warning clears naturally.
|
||||
|
||||
**Tasks:**
|
||||
|
||||
1. Check PR status page weekly for warning persistence
|
||||
2. If warning persists after 4 weeks, try Option 2 (manual workflow dispatch)
|
||||
3. If warning persists after 8 weeks, open GitHub Support ticket
|
||||
|
||||
**Success Criteria:**
|
||||
|
||||
- Warning clears within 4-8 weeks as GitHub Security updates tracking
|
||||
|
||||
**Estimated Time:** 5 minutes/week
|
||||
@@ -341,6 +380,7 @@ jobs:
|
||||
### Impact Analysis
|
||||
|
||||
**If We Do Nothing:**
|
||||
|
||||
- Security scanning: ✅ UNAFFECTED (fully functional)
|
||||
- Code quality: ✅ UNAFFECTED
|
||||
- Developer experience: ✅ UNAFFECTED
|
||||
@@ -348,6 +388,7 @@ jobs:
|
||||
- Compliance audits: ✅ PASS (coverage is complete, documented)
|
||||
|
||||
**If We Implement Phase 1 (Documentation):**
|
||||
|
||||
- Security scanning: ✅ UNAFFECTED
|
||||
- Code quality: ✅ IMPROVED (better documentation)
|
||||
- Developer experience: ✅ IMPROVED (clearer history)
|
||||
@@ -361,6 +402,7 @@ jobs:
|
||||
### Workflow File Comparison
|
||||
|
||||
#### security-weekly-rebuild.yml
|
||||
|
||||
```yaml
|
||||
name: Weekly Security Rebuild
|
||||
on:
|
||||
@@ -376,6 +418,7 @@ jobs:
|
||||
```
|
||||
|
||||
#### docker-build.yml (current)
|
||||
|
||||
```yaml
|
||||
name: Docker Build, Publish & Test
|
||||
on:
|
||||
@@ -396,6 +439,7 @@ jobs:
|
||||
```
|
||||
|
||||
#### docker-publish.yml (DELETED on 2025-12-21)
|
||||
|
||||
```yaml
|
||||
name: Docker Build, Publish & Test # ← Same name as docker-build.yml
|
||||
on:
|
||||
@@ -414,6 +458,7 @@ jobs:
|
||||
```
|
||||
|
||||
**Migration Notes:**
|
||||
|
||||
- ✅ Job name `build-and-push` preserved for continuity
|
||||
- ✅ All Trivy functionality preserved
|
||||
- ✅ Enhanced with SBOM generation and attestation
|
||||
@@ -425,12 +470,14 @@ jobs:
|
||||
## Dependencies
|
||||
|
||||
### Files to Review/Update (Phase 1)
|
||||
|
||||
- [ ] `CHANGELOG.md` - Add entry for workflow migration
|
||||
- [ ] `SECURITY.md` - Document security scanning coverage
|
||||
- [ ] `.github/workflows/docker-build.yml` - Add header comment
|
||||
- [ ] `.github/workflows/README.md` - Create workflow documentation (optional)
|
||||
|
||||
### No Changes Required (Already Compliant)
|
||||
|
||||
- ✅ `.gitignore` - No new files/folders added
|
||||
- ✅ `.dockerignore` - No Docker changes
|
||||
- ✅ `.codecov.yml` - No coverage changes
|
||||
@@ -441,6 +488,7 @@ jobs:
|
||||
## Success Criteria
|
||||
|
||||
### Phase 1 Success (Documentation)
|
||||
|
||||
- [x] Plan document created and comprehensive
|
||||
- [x] Root cause identified (workflow file renamed)
|
||||
- [x] Security coverage verified (all scans active)
|
||||
@@ -451,12 +499,14 @@ jobs:
|
||||
- [ ] No linting or formatting errors
|
||||
|
||||
### Phase 2 Success (Verification)
|
||||
|
||||
- [ ] All workflows show successful recent runs
|
||||
- [ ] Trivy SARIF results visible in Security tab
|
||||
- [ ] No scan failures in last 30 days
|
||||
- [ ] Weekly security rebuild on schedule
|
||||
|
||||
### Phase 3 Success (Monitoring)
|
||||
|
||||
- [ ] GitHub Security warning tracked weekly
|
||||
- [ ] Warning clears within 8 weeks OR GitHub Support ticket opened
|
||||
- [ ] No functional issues with security scanning
|
||||
@@ -468,6 +518,7 @@ jobs:
|
||||
### Why Not Fix the "Warning" Immediately?
|
||||
|
||||
**Considered Approaches:**
|
||||
|
||||
1. **Re-create docker-publish.yml as wrapper**
|
||||
- ❌ Creates maintenance burden
|
||||
- ❌ Doesn't solve root cause
|
||||
@@ -484,6 +535,7 @@ jobs:
|
||||
- ⚠️ Should be last resort after monitoring
|
||||
|
||||
**Selected Approach: Document and Monitor**
|
||||
|
||||
- ✅ Zero risk to existing functionality
|
||||
- ✅ Improves project documentation
|
||||
- ✅ Provides audit trail
|
||||
@@ -494,26 +546,34 @@ jobs:
|
||||
## Questions and Answers
|
||||
|
||||
### Q: Is this a security vulnerability?
|
||||
|
||||
**A:** No. This is a tracking/reporting issue in GitHub Advanced Security's workflow registry. All security scanning functionality is active and enhanced compared to the deleted workflow.
|
||||
|
||||
### Q: Will this block merging the PR?
|
||||
|
||||
**A:** No. GitHub Advanced Security warnings are informational and do not block merges. The warning indicates a tracking discrepancy, not a functional security gap.
|
||||
|
||||
### Q: Should we re-create docker-publish.yml?
|
||||
|
||||
**A:** No. Re-creating the file would be symptom patching and create maintenance burden. The functionality exists in `docker-build.yml` with enhancements.
|
||||
|
||||
### Q: How long will the warning persist?
|
||||
|
||||
**A:** Unknown. It depends on GitHub's internal tracking cache refresh cycle. Typically, these warnings clear within 4-8 weeks as GitHub's systems update. If it persists beyond 8 weeks, we can escalate to GitHub Support.
|
||||
|
||||
### Q: Does this affect compliance audits?
|
||||
|
||||
**A:** No. This document provides a complete audit trail showing:
|
||||
|
||||
1. Security scanning coverage is complete
|
||||
2. Functionality was enhanced, not reduced
|
||||
3. The warning is a false positive from filename tracking
|
||||
4. All Trivy scans are active and uploading to Security tab
|
||||
|
||||
### Q: What if reviewers question the warning?
|
||||
|
||||
**A:** Point them to this document which provides:
|
||||
|
||||
1. Complete investigation summary
|
||||
2. Root cause analysis
|
||||
3. Risk assessment (LOW severity, tracking issue only)
|
||||
@@ -528,6 +588,7 @@ jobs:
|
||||
**Security Status:** ✅ **NO SECURITY GAPS** - All Trivy scanning is active, functional, and enhanced compared to the deleted workflow.
|
||||
|
||||
**Recommended Action:**
|
||||
|
||||
1. ✅ **Implement Phase 1** - Document the migration (30 minutes, zero risk)
|
||||
2. ✅ **Implement Phase 2** - Verify scanning functionality (15 minutes, read-only)
|
||||
3. ✅ **Implement Phase 3** - Monitor warning status (5 min/week, optional escalation)
|
||||
@@ -543,19 +604,22 @@ jobs:
|
||||
## References
|
||||
|
||||
### Git Commits
|
||||
|
||||
- `f640524b` - Removed docker-publish.yml (Dec 21, 2025)
|
||||
- `e58fcb71` - Created docker-build.yml (initial)
|
||||
- `8311d68d` - Updated docker-build.yml buildx action (latest)
|
||||
|
||||
### Workflow Files
|
||||
|
||||
- `.github/workflows/security-weekly-rebuild.yml` - Weekly security rebuild
|
||||
- `.github/workflows/docker-build.yml` - Current build and publish workflow
|
||||
- `.github/workflows/docker-publish.yml` - DELETED (replaced by docker-build.yml)
|
||||
|
||||
### Documentation
|
||||
- GitHub Advanced Security: https://docs.github.com/en/code-security
|
||||
- Trivy Scanner: https://github.com/aquasecurity/trivy
|
||||
- SARIF Format: https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning
|
||||
|
||||
- GitHub Advanced Security: <https://docs.github.com/en/code-security>
|
||||
- Trivy Scanner: <https://github.com/aquasecurity/trivy>
|
||||
- SARIF Format: <https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
Successfully resolved issue where PR status checks didn't appear when docs-to-issues workflow ran.
|
||||
|
||||
**Documentation:**
|
||||
|
||||
- **Implementation Summary**: [docs/implementation/DOCS_TO_ISSUES_FIX_2026-01-11.md](../implementation/DOCS_TO_ISSUES_FIX_2026-01-11.md)
|
||||
- **QA Report**: [docs/reports/qa_docs_to_issues_workflow_fix.md](../reports/qa_docs_to_issues_workflow_fix.md)
|
||||
- **Archived Plan**: [docs/plans/archive/docs_to_issues_workflow_fix_2026-01-11.md](archive/docs_to_issues_workflow_fix_2026-01-11.md)
|
||||
@@ -33,6 +34,7 @@ Successfully resolved issue where PR status checks didn't appear when docs-to-is
|
||||
The CI workflow investigation and documentation has been completed. Both issues were determined to be false positives or expected GitHub behavior with no security gaps.
|
||||
|
||||
**Final Documentation:**
|
||||
|
||||
- **Implementation Summary**: [docs/implementation/CI_WORKFLOW_FIXES_2026-01-11.md](../implementation/CI_WORKFLOW_FIXES_2026-01-11.md)
|
||||
- **QA Report**: [docs/reports/qa_report.md](../reports/qa_report.md)
|
||||
- **Archived Plan**: [docs/plans/archive/GITHUB_SECURITY_WARNING_RESOLUTION_PLAN_2026-01-11.md](archive/GITHUB_SECURITY_WARNING_RESOLUTION_PLAN_2026-01-11.md)
|
||||
@@ -46,6 +48,7 @@ The CI workflow investigation and documentation has been completed. Both issues
|
||||
Successfully fixed workflow orchestration issue where supply-chain-verify was running before docker-build completed, causing verification to skip on PRs.
|
||||
|
||||
**Documentation:**
|
||||
|
||||
- **Implementation Summary**: [docs/implementation/WORKFLOW_ORCHESTRATION_FIX.md](../implementation/WORKFLOW_ORCHESTRATION_FIX.md)
|
||||
- **QA Report**: [docs/reports/qa_report_workflow_orchestration.md](../reports/qa_report_workflow_orchestration.md)
|
||||
- **Archived Plan**: [docs/plans/archive/workflow_orchestration_fix_2026-01-11.md](archive/workflow_orchestration_fix_2026-01-11.md)
|
||||
@@ -59,6 +62,7 @@ Successfully fixed workflow orchestration issue where supply-chain-verify was ru
|
||||
Successfully resolved CI/CD failures in the Supply Chain Verification workflow caused by Grype SBOM format mismatch.
|
||||
|
||||
**Documentation:**
|
||||
|
||||
- **Implementation Summary**: [docs/implementation/GRYPE_SBOM_REMEDIATION.md](../implementation/GRYPE_SBOM_REMEDIATION.md)
|
||||
- **QA Report**: [docs/reports/qa_report.md](../reports/qa_report.md)
|
||||
- **Archived Plan**: [docs/plans/archive/grype_sbom_remediation_2026-01-10.md](archive/grype_sbom_remediation_2026-01-10.md)
|
||||
@@ -93,6 +97,7 @@ When a specification is complete:
|
||||
## Archive Location
|
||||
|
||||
Completed and archived specifications can be found in:
|
||||
|
||||
- [docs/plans/archive/](archive/)
|
||||
|
||||
---
|
||||
|
||||
@@ -40,6 +40,7 @@ syft ${IMAGE} -o spdx-json > sbom-generated.json || {
|
||||
\`\`\`
|
||||
|
||||
**Issues**:
|
||||
|
||||
- Generates SBOM in **SPDX-JSON** format
|
||||
- Error handling exits with code 0, masking failures
|
||||
- Empty or malformed file may be created if image doesn't exist
|
||||
@@ -55,6 +56,7 @@ grype sbom:sbom-generated.json -o json > vuln-scan.json || {
|
||||
\`\`\`
|
||||
|
||||
**Issues**:
|
||||
|
||||
- Assumes SBOM file is valid without checking
|
||||
- Fails if SBOM is empty, corrupted, or malformed
|
||||
- Error is suppressed with `exit 0`
|
||||
@@ -83,11 +85,13 @@ grype sbom:sbom-generated.json -o json > vuln-scan.json || {
|
||||
### Supported Formats (Anchore Documentation)
|
||||
|
||||
**Grype** supports:
|
||||
|
||||
- Syft JSON (native format)
|
||||
- SPDX JSON/XML
|
||||
- CycloneDX JSON/XML
|
||||
|
||||
**Syft** outputs:
|
||||
|
||||
- Syft JSON
|
||||
- SPDX JSON/XML
|
||||
- CycloneDX JSON/XML
|
||||
@@ -126,6 +130,7 @@ grype sbom:sbom-generated.json -o json > vuln-scan.json || {
|
||||
Combine format standardization, validation, and conditional execution.
|
||||
|
||||
**Phase 1** (Immediate - 2-4 hours):
|
||||
|
||||
1. Standardize on **CycloneDX-JSON** format (aligns with docker-build.yml)
|
||||
2. Add image existence check before SBOM generation
|
||||
3. Add comprehensive SBOM validation before Grype scan
|
||||
@@ -133,6 +138,7 @@ Combine format standardization, validation, and conditional execution.
|
||||
5. Skip gracefully when image doesn't exist
|
||||
|
||||
**Phase 2** (Future enhancement - 4-8 hours):
|
||||
|
||||
- Retrieve attested SBOM from registry instead of regenerating
|
||||
- Eliminates duplication and ensures consistency
|
||||
|
||||
@@ -147,6 +153,7 @@ Combine format standardization, validation, and conditional execution.
|
||||
**Location**: After "Determine Image Tag" step (after line 54)
|
||||
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Check Image Availability
|
||||
id: image-check
|
||||
env:
|
||||
@@ -187,6 +194,7 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
|
||||
**Before**:
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Verify SBOM Completeness
|
||||
env:
|
||||
IMAGE: ghcr.io/${{ github.repository_owner }}/charon:${{ steps.tag.outputs.tag }}
|
||||
@@ -194,6 +202,7 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
|
||||
**After**:
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Verify SBOM Completeness
|
||||
if: steps.image-check.outputs.exists == 'true'
|
||||
env:
|
||||
@@ -205,27 +214,31 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
**Location**: New step after "Verify SBOM Completeness" (after line 77)
|
||||
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Validate SBOM File
|
||||
id: validate-sbom
|
||||
if: steps.image-check.outputs.exists == 'true'
|
||||
run: |
|
||||
echo "Validating SBOM file..."
|
||||
|
||||
# Check file exists
|
||||
# Check file exists
|
||||
|
||||
if [[ ! -f sbom-generated.json ]]; then
|
||||
echo "❌ SBOM file does not exist"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check file is non-empty
|
||||
# Check file is non-empty
|
||||
|
||||
if [[ ! -s sbom-generated.json ]]; then
|
||||
echo "❌ SBOM file is empty"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Validate JSON structure
|
||||
# Validate JSON structure
|
||||
|
||||
if ! jq empty sbom-generated.json 2>/dev/null; then
|
||||
echo "❌ SBOM file contains invalid JSON"
|
||||
cat sbom-generated.json
|
||||
@@ -233,7 +246,8 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Validate CycloneDX structure
|
||||
# Validate CycloneDX structure
|
||||
|
||||
BOMFORMAT=$(jq -r '.bomFormat // "missing"' sbom-generated.json)
|
||||
SPECVERSION=$(jq -r '.specVersion // "missing"' sbom-generated.json)
|
||||
COMPONENTS=$(jq '.components // [] | length' sbom-generated.json)
|
||||
@@ -262,6 +276,7 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
**Location**: Lines 81-103 (replace entire "Scan for Vulnerabilities" step)
|
||||
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Scan for Vulnerabilities
|
||||
if: steps.validate-sbom.outputs.valid == 'true'
|
||||
env:
|
||||
@@ -272,7 +287,8 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
echo "SBOM size: $(wc -c < sbom-generated.json) bytes"
|
||||
echo ""
|
||||
|
||||
# Run Grype with explicit path and better error handling
|
||||
# Run Grype with explicit path and better error handling
|
||||
|
||||
if ! grype sbom:./sbom-generated.json --output json --file vuln-scan.json; then
|
||||
echo ""
|
||||
echo "❌ Grype scan failed"
|
||||
@@ -290,11 +306,13 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
echo "✅ Grype scan completed successfully"
|
||||
echo ""
|
||||
|
||||
# Display human-readable results
|
||||
# Display human-readable results
|
||||
|
||||
echo "Vulnerability summary:"
|
||||
grype sbom:./sbom-generated.json --output table || true
|
||||
|
||||
# Parse and categorize results
|
||||
# Parse and categorize results
|
||||
|
||||
CRITICAL=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' vuln-scan.json 2>/dev/null || echo "0")
|
||||
HIGH=$(jq '[.matches[] | select(.vulnerability.severity == "High")] | length' vuln-scan.json 2>/dev/null || echo "0")
|
||||
MEDIUM=$(jq '[.matches[] | select(.vulnerability.severity == "Medium")] | length' vuln-scan.json 2>/dev/null || echo "0")
|
||||
@@ -307,12 +325,14 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
echo " Medium: ${MEDIUM}"
|
||||
echo " Low: ${LOW}"
|
||||
|
||||
# Set warnings for critical vulnerabilities
|
||||
# Set warnings for critical vulnerabilities
|
||||
|
||||
if [[ ${CRITICAL} -gt 0 ]]; then
|
||||
echo "::warning::${CRITICAL} critical vulnerabilities found"
|
||||
fi
|
||||
|
||||
# Store for PR comment
|
||||
# Store for PR comment
|
||||
|
||||
echo "CRITICAL_VULNS=${CRITICAL}" >> $GITHUB_ENV
|
||||
echo "HIGH_VULNS=${HIGH}" >> $GITHUB_ENV
|
||||
echo "MEDIUM_VULNS=${MEDIUM}" >> $GITHUB_ENV
|
||||
@@ -344,6 +364,7 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
**Location**: Lines 107-122 (replace entire "Comment on PR" step)
|
||||
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Comment on PR
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
@@ -388,6 +409,7 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
issue_number: context.issue.number,
|
||||
body: body
|
||||
});
|
||||
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
@@ -399,40 +421,52 @@ syft ${IMAGE} -o cyclonedx-json > sbom-generated.json || {
|
||||
#### 1. Local SBOM Generation and Validation
|
||||
|
||||
\`\`\`bash
|
||||
|
||||
# Test SBOM generation with existing image
|
||||
|
||||
docker pull ghcr.io/wikid82/charon:latest
|
||||
|
||||
# Generate SBOM in CycloneDX format
|
||||
|
||||
syft ghcr.io/wikid82/charon:latest -o cyclonedx-json > test-sbom.json
|
||||
|
||||
# Validate JSON structure
|
||||
|
||||
jq empty test-sbom.json && echo "✅ Valid JSON" || echo "❌ Invalid JSON"
|
||||
|
||||
# Check CycloneDX fields
|
||||
|
||||
jq '.bomFormat, .specVersion, .components | length' test-sbom.json
|
||||
|
||||
# Test Grype scan
|
||||
|
||||
grype sbom:./test-sbom.json -o table
|
||||
|
||||
# Test with explicit path
|
||||
|
||||
grype sbom:./test-sbom.json -o json > vuln-test.json
|
||||
|
||||
# Check results
|
||||
|
||||
jq '.matches | length' vuln-test.json
|
||||
\`\`\`
|
||||
|
||||
#### 2. Test Empty/Invalid SBOM Handling
|
||||
|
||||
\`\`\`bash
|
||||
|
||||
# Test with empty file
|
||||
|
||||
touch empty.json
|
||||
grype sbom:./empty.json 2>&1 | grep -i "format"
|
||||
|
||||
# Test with invalid JSON
|
||||
|
||||
echo "{invalid json" > invalid.json
|
||||
grype sbom:./invalid.json 2>&1 | grep -i "format"
|
||||
|
||||
# Test with missing fields
|
||||
|
||||
echo '{"bomFormat":"test"}' > incomplete.json
|
||||
grype sbom:./incomplete.json 2>&1 | grep -i "format"
|
||||
\`\`\`
|
||||
@@ -440,10 +474,13 @@ grype sbom:./incomplete.json 2>&1 | grep -i "format"
|
||||
#### 3. Test Image Availability Check
|
||||
|
||||
\`\`\`bash
|
||||
|
||||
# Test manifest check for existing image
|
||||
|
||||
docker manifest inspect ghcr.io/wikid82/charon:latest
|
||||
|
||||
# Test manifest check for non-existent image
|
||||
|
||||
docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
\`\`\`
|
||||
|
||||
@@ -495,11 +532,14 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
3. **Alternative: Pin Tool Versions**
|
||||
If the issue is version-related:
|
||||
\`\`\`yaml
|
||||
|
||||
# Pin Syft version
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin v0.100.0
|
||||
|
||||
curl -sSfL <https://raw.githubusercontent.com/anchore/syft/main/install.sh> | sh -s -- -b /usr/local/bin v0.100.0
|
||||
|
||||
# Pin Grype version
|
||||
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin v0.74.0
|
||||
|
||||
curl -sSfL <https://raw.githubusercontent.com/anchore/grype/main/install.sh> | sh -s -- -b /usr/local/bin v0.74.0
|
||||
\`\`\`
|
||||
|
||||
### Investigation Steps
|
||||
@@ -515,12 +555,14 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
## Dependencies and Prerequisites
|
||||
|
||||
### Tool Versions
|
||||
|
||||
- **Syft**: Latest from install script (currently v0.100+)
|
||||
- **Grype**: Latest from install script (currently v0.74+)
|
||||
- **Docker**: v20+ (available in GitHub runners)
|
||||
- **jq**: v1.6+ (available in GitHub runners)
|
||||
|
||||
### GitHub Permissions Required
|
||||
|
||||
- `contents: read` - Repository code access
|
||||
- `packages: read` - Container registry access
|
||||
- `pull-requests: write` - Comment on PRs
|
||||
@@ -529,6 +571,7 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
- `attestations: write` - Create/verify attestations
|
||||
|
||||
### External Dependencies
|
||||
|
||||
- GitHub Container Registry (ghcr.io) must be accessible
|
||||
- Anchore install scripts must be available
|
||||
- Internet access required for tool installation
|
||||
@@ -538,11 +581,13 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
## Implementation Checklist
|
||||
|
||||
### Preparation
|
||||
|
||||
- [ ] Review current workflow file
|
||||
- [ ] Document current behavior
|
||||
- [ ] Create feature branch
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] Add image existence check step
|
||||
- [ ] Change SBOM format from SPDX to CycloneDX
|
||||
- [ ] Add SBOM validation step
|
||||
@@ -552,6 +597,7 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
- [ ] Update workflow documentation
|
||||
|
||||
### Testing
|
||||
|
||||
- [ ] Test locally with existing image
|
||||
- [ ] Test with empty SBOM file
|
||||
- [ ] Test with invalid JSON
|
||||
@@ -562,12 +608,14 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
- [ ] Verify success path
|
||||
|
||||
### Documentation
|
||||
|
||||
- [ ] Update README if needed
|
||||
- [ ] Document SBOM format choice
|
||||
- [ ] Add troubleshooting guide
|
||||
- [ ] Update CI/CD documentation
|
||||
|
||||
### Deployment
|
||||
|
||||
- [ ] Create PR with changes
|
||||
- [ ] Code review
|
||||
- [ ] Merge to main
|
||||
@@ -609,6 +657,7 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
## Success Metrics
|
||||
|
||||
### Technical Metrics
|
||||
|
||||
- Workflow success rate: 100% on valid images
|
||||
- SBOM validation accuracy: 100%
|
||||
- Grype scan completion rate: 100% on valid SBOMs
|
||||
@@ -616,12 +665,14 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
- False negative rate: 0%
|
||||
|
||||
### Operational Metrics
|
||||
|
||||
- Time to detect vulnerability: < 5 minutes after image build
|
||||
- Mean time to remediate issues: Immediate (next workflow run)
|
||||
- Manual intervention required: 0
|
||||
- CI/CD pipeline reliability: > 99%
|
||||
|
||||
### Quality Metrics
|
||||
|
||||
- Zero "format not recognized" errors in 30 days
|
||||
- Clear, actionable error messages
|
||||
- Comprehensive workflow logs
|
||||
@@ -636,6 +687,7 @@ docker manifest inspect ghcr.io/wikid82/charon:pr-99999 2>&1
|
||||
Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
|
||||
\`\`\`yaml
|
||||
|
||||
- name: Retrieve Attested SBOM
|
||||
if: steps.image-check.outputs.exists == 'true'
|
||||
env:
|
||||
@@ -644,7 +696,8 @@ Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
run: |
|
||||
echo "Retrieving attested SBOM from registry..."
|
||||
|
||||
# Download attestation using GitHub CLI
|
||||
# Download attestation using GitHub CLI
|
||||
|
||||
gh attestation verify oci://${IMAGE} \
|
||||
--owner ${{ github.repository_owner }} \
|
||||
--format json > attestation.json 2>&1 || {
|
||||
@@ -652,10 +705,12 @@ Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Extract SBOM from attestation
|
||||
# Extract SBOM from attestation
|
||||
|
||||
jq -r '.predicate' attestation.json > sbom-attested.json
|
||||
|
||||
# Validate and use
|
||||
# Validate and use
|
||||
|
||||
if jq empty sbom-attested.json 2>/dev/null; then
|
||||
echo "✅ Retrieved attested SBOM"
|
||||
mv sbom-attested.json sbom-generated.json
|
||||
@@ -665,12 +720,14 @@ Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
\`\`\`
|
||||
|
||||
**Benefits**:
|
||||
|
||||
- Single source of truth
|
||||
- Eliminates duplication
|
||||
- Uses verified, signed SBOM
|
||||
- Aligns with supply chain best practices
|
||||
|
||||
**Requirements**:
|
||||
|
||||
- GitHub CLI with attestation support
|
||||
- Attestation must be published to registry
|
||||
- Additional testing for attestation retrieval
|
||||
@@ -680,11 +737,13 @@ Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
## Related Documentation
|
||||
|
||||
### Internal References
|
||||
|
||||
- [.github/workflows/supply-chain-verify.yml](.github/workflows/supply-chain-verify.yml)
|
||||
- [.github/workflows/docker-build.yml](.github/workflows/docker-build.yml)
|
||||
- Project README (Security section)
|
||||
|
||||
### External References
|
||||
|
||||
- [Anchore Grype Documentation](https://github.com/anchore/grype)
|
||||
- [Anchore Syft Documentation](https://github.com/anchore/syft)
|
||||
- [CycloneDX Specification](https://cyclonedx.org/specification/overview/)
|
||||
@@ -702,6 +761,7 @@ Instead of regenerating SBOM, retrieve the one created by docker-build:
|
||||
**Review Status**: Ready for Review
|
||||
|
||||
**Required Reviewers**:
|
||||
|
||||
- [ ] DevOps Lead / CI/CD Owner
|
||||
- [ ] Security Team Representative
|
||||
- [ ] Repository Maintainer
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
**Translation:** Staticcheck must be a **COMMIT GATE** - failures must BLOCK the commit, forcing immediate fix before commit succeeds.
|
||||
|
||||
**Current Gaps:**
|
||||
|
||||
- ✅ Staticcheck IS enabled in golangci-lint (`.golangci.yml` line 14)
|
||||
- ✅ Staticcheck IS running in CI via golangci-lint-action (`quality-checks.yml` line 65-70)
|
||||
- ❌ Staticcheck is NOT running in local pre-commit hooks as a BLOCKING gate
|
||||
@@ -28,6 +29,7 @@
|
||||
- ⚠️ Test files excluded from staticcheck in `.golangci.yml` (line 68-70)
|
||||
|
||||
**Why This Matters:**
|
||||
|
||||
- Developers see staticcheck warnings/errors in VS Code editor
|
||||
- **These issues are NOT blocked at commit time** ← CRITICAL PROBLEM
|
||||
- CI failures don't block merges (continue-on-error: true)
|
||||
@@ -40,10 +42,12 @@
|
||||
### Supervisor Critical Feedback & Decisions
|
||||
|
||||
**Feedback #1: Redundancy Issue**
|
||||
|
||||
- Current plan creates duplicate staticcheck runs (standalone + golangci-lint)
|
||||
- **Decision:** Use **Hybrid Approach** (Supervisor's recommendation) - explained below
|
||||
|
||||
**Feedback #2: Performance Benchmarks Required**
|
||||
|
||||
- **ACTUAL MEASUREMENT (2026-01-11):**
|
||||
- Command: `time staticcheck ./...` (in backend/)
|
||||
- **Runtime: 15.3 seconds (real), 44s CPU (user), 4.3s I/O (sys)**
|
||||
@@ -52,20 +56,24 @@
|
||||
- Exit code: 1 (FAILS - this is what we want for blocking)
|
||||
|
||||
**Feedback #3: Version Pinning**
|
||||
|
||||
- **Decision:** Pin to `@2024.1.1` in installation docs
|
||||
- Note: Installation of 2024.1.1 failed due to compiler bug; fallback to @latest (2025.1.1) works
|
||||
- Will document @latest with version verification step
|
||||
|
||||
**Feedback #4: CI Alignment Issue**
|
||||
|
||||
- CI has `continue-on-error: true` for golangci-lint (line 71 in quality-checks.yml)
|
||||
- **Local will be STRICTER than CI** - local BLOCKS, CI warns
|
||||
- **Decision:** Document this discrepancy; recommend CI fix in Phase 6 (future work)
|
||||
|
||||
**Feedback #5: Test File Exclusion**
|
||||
|
||||
- `.golangci.yml` line 68-70: staticcheck excluded from `_test.go` files
|
||||
- **Decision:** Match this behavior in new hook - exclude test files
|
||||
|
||||
**Feedback #6: Pre-flight Check**
|
||||
|
||||
- **Decision:** Add verification step that staticcheck is installed before running
|
||||
|
||||
---
|
||||
@@ -75,6 +83,7 @@
|
||||
**Why Hybrid Approach?**
|
||||
|
||||
**Advantages:**
|
||||
|
||||
1. **No Duplication:** Uses existing golangci-lint infrastructure
|
||||
2. **Consistent Configuration:** Single source of truth (`.golangci.yml`)
|
||||
3. **Test Exclusions Aligned:** Automatically respects test file exclusions
|
||||
@@ -82,17 +91,20 @@
|
||||
5. **Standard Practice:** Many projects use golangci-lint with selective linters for pre-commit
|
||||
|
||||
**Performance Comparison:**
|
||||
|
||||
- Standalone staticcheck: **15.3s**
|
||||
- golangci-lint (staticcheck only): ~**18-22s** (estimated +20% overhead)
|
||||
- golangci-lint (all 8 linters): 30-60s (too slow for pre-commit)
|
||||
|
||||
**Implementation Strategy:**
|
||||
|
||||
- Create lightweight pre-commit hook using golangci-lint with **ONLY fast linters**
|
||||
- Enable: staticcheck, govet, errcheck, ineffassign, unused
|
||||
- Disable: gosec, gocritic, bodyclose (slower or less critical)
|
||||
- **CRITICAL:** Hook MUST exit with non-zero code to BLOCK commits
|
||||
|
||||
**Why NOT Standalone?**
|
||||
|
||||
- Supervisor correctly identified duplication concern
|
||||
- Maintaining two configurations (hook + `.golangci.yml`) creates drift risk
|
||||
- golangci-lint overhead is acceptable (3-7s) for consistency benefits
|
||||
@@ -123,11 +135,13 @@
|
||||
**File:** `backend/.golangci.yml`
|
||||
|
||||
**Staticcheck Configuration:**
|
||||
|
||||
- ✅ Line 14: `- staticcheck` (enabled in linters.enable)
|
||||
- ✅ Lines 68-70: **Test file exclusions** (staticcheck excluded from `_test.go`)
|
||||
- **IMPORTANT:** New hook MUST match this exclusion behavior
|
||||
|
||||
**Other Enabled Linters:**
|
||||
|
||||
- Fast: govet, ineffassign, unused, errcheck, staticcheck
|
||||
- Slower: bodyclose, gocritic, gosec
|
||||
|
||||
@@ -136,11 +150,13 @@
|
||||
**File:** `.github/workflows/quality-checks.yml`
|
||||
|
||||
**Lines 65-71:**
|
||||
|
||||
- Runs golangci-lint (includes staticcheck) in CI
|
||||
- **⚠️ CRITICAL ISSUE:** `continue-on-error: true` means failures **don't block merges**
|
||||
- This creates **local stricter than CI** situation
|
||||
|
||||
**Implication:**
|
||||
|
||||
- Local pre-commit will BLOCK on staticcheck errors
|
||||
- CI will ALLOW merge with same errors
|
||||
- **Recommendation:** Remove `continue-on-error: true` in future PR (Phase 6)
|
||||
@@ -148,6 +164,7 @@
|
||||
#### System Environment
|
||||
|
||||
**Staticcheck Installation Status:**
|
||||
|
||||
- ✅ **NOW INSTALLED:** staticcheck 2025.1.1 (0.6.1)
|
||||
- Location: `$GOPATH/bin/staticcheck`
|
||||
- **Benchmark Complete:** 15.3s runtime on full codebase
|
||||
@@ -219,6 +236,7 @@ issues:
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
|
||||
- **Pre-flight check:** Verifies golangci-lint is installed before running
|
||||
- **Fast config:** Uses `.golangci-fast.yml` (only 5 linters, ~20s runtime)
|
||||
- **BLOCKING:** Exit code propagates - failures BLOCK commit
|
||||
@@ -231,6 +249,7 @@ issues:
|
||||
**Location:** Development Setup section (after pre-commit installation)
|
||||
|
||||
**Addition:**
|
||||
|
||||
```markdown
|
||||
### Go Development Tools
|
||||
|
||||
@@ -300,13 +319,13 @@ golangci-lint --version
|
||||
|
||||
.PHONY: lint-fast
|
||||
lint-fast:
|
||||
@echo "Running fast linters (staticcheck, govet, errcheck, ineffassign, unused)..."
|
||||
cd backend && golangci-lint run --config .golangci-fast.yml ./...
|
||||
@echo "Running fast linters (staticcheck, govet, errcheck, ineffassign, unused)..."
|
||||
cd backend && golangci-lint run --config .golangci-fast.yml ./...
|
||||
|
||||
.PHONY: lint-staticcheck
|
||||
lint-staticcheck:
|
||||
@echo "Running staticcheck only..."
|
||||
cd backend && golangci-lint run --config .golangci-fast.yml --disable-all --enable staticcheck ./...
|
||||
@echo "Running staticcheck only..."
|
||||
cd backend && golangci-lint run --config .golangci-fast.yml --disable-all --enable staticcheck ./...
|
||||
```
|
||||
|
||||
---
|
||||
@@ -504,6 +523,7 @@ make lint-staticcheck # Should run staticcheck only
|
||||
**File:** `docs/implementation/STATICCHECK_BLOCKING_INTEGRATION_COMPLETE.md`
|
||||
|
||||
**Contents:**
|
||||
|
||||
```markdown
|
||||
# Staticcheck BLOCKING Pre-Commit Integration - Implementation Complete
|
||||
|
||||
@@ -678,12 +698,14 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
**Line 71:** Remove or change `continue-on-error: true` to `continue-on-error: false`
|
||||
|
||||
**Requires:**
|
||||
|
||||
- Team discussion and agreement
|
||||
- Ensure existing codebase passes golangci-lint cleanly
|
||||
- May need to fix existing issues first
|
||||
- Consider adding lint-fixes PR before enforcing
|
||||
|
||||
**Trade-offs:**
|
||||
|
||||
- **Pro:** Consistent quality enforcement (local + CI)
|
||||
- **Pro:** Prevents merging code with linter issues
|
||||
- **Con:** May slow down initial adoption
|
||||
@@ -745,6 +767,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
### Performance Benchmarks (ACTUAL - Measured 2026-01-11)
|
||||
|
||||
**Environment:**
|
||||
|
||||
- System: Development environment
|
||||
- Backend: Go 1.x codebase
|
||||
- Lines of Go code: ~XX,XXX (estimate)
|
||||
@@ -759,12 +782,14 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
| go vet | <5s | - | - | 0 | (active) |
|
||||
|
||||
**Analysis:**
|
||||
|
||||
- ✅ Fast config overhead acceptable: +30% vs standalone (~5s)
|
||||
- ✅ Well under 30s target for pre-commit
|
||||
- ✅ BLOCKING behavior confirmed (exit code 1)
|
||||
- ✅ Consistency: Both tools find same staticcheck issues
|
||||
|
||||
**Current Issues Found (2026-01-11):**
|
||||
|
||||
- 1x Deprecated API (SA1019): `filepath.HasPrefix`
|
||||
- 5x Unused values (SA4006): test setup code
|
||||
- 1x Simplification opportunity (S1017): if statement
|
||||
@@ -780,11 +805,13 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
### File Reference Summary
|
||||
|
||||
**Files to Create:**
|
||||
|
||||
1. `backend/.golangci-fast.yml` - Lightweight config for pre-commit (5 linters)
|
||||
2. `docs/implementation/STATICCHECK_BLOCKING_INTEGRATION_COMPLETE.md` - Implementation summary
|
||||
3. `docs/plans/archive/staticcheck_blocking_integration_2026-01-11.md` - Archived spec (after completion)
|
||||
|
||||
**Files to Modify:**
|
||||
|
||||
1. `.pre-commit-config.yaml` (line ~44: add golangci-lint-fast hook after go-vet)
|
||||
2. `.vscode/tasks.json` (line ~211: add 2 new lint tasks after go-vet task)
|
||||
3. `Makefile` (line ~141: add lint-fast and lint-staticcheck targets after lint-backend)
|
||||
@@ -796,6 +823,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
6. `CHANGELOG.md` (Unreleased section: add breaking change notice)
|
||||
|
||||
**Files to Review (No Changes):**
|
||||
|
||||
- `backend/.golangci.yml` - Reference for test exclusions (lines 68-70)
|
||||
- `.github/workflows/quality-checks.yml` - Reference for CI config (line 71: continue-on-error)
|
||||
|
||||
@@ -806,6 +834,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
**If problems occur during implementation:**
|
||||
|
||||
1. **Remove pre-commit hook:**
|
||||
|
||||
```bash
|
||||
# Edit .pre-commit-config.yaml - remove golangci-lint-fast hook
|
||||
git checkout HEAD -- .pre-commit-config.yaml
|
||||
@@ -814,16 +843,19 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
```
|
||||
|
||||
2. **Delete fast config:**
|
||||
|
||||
```bash
|
||||
rm backend/.golangci-fast.yml
|
||||
```
|
||||
|
||||
3. **Revert documentation:**
|
||||
|
||||
```bash
|
||||
git checkout HEAD -- README.md CHANGELOG.md .github/instructions/copilot-instructions.md
|
||||
```
|
||||
|
||||
4. **Remove VS Code tasks and Makefile targets:**
|
||||
|
||||
```bash
|
||||
git checkout HEAD -- .vscode/tasks.json Makefile
|
||||
```
|
||||
@@ -831,6 +863,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
**Rollback Time:** < 5 minutes (all changes are additive, easy to remove)
|
||||
|
||||
**Risk Mitigation:**
|
||||
|
||||
- Test each phase independently before proceeding
|
||||
- Keep backup of original files during implementation
|
||||
- Document any unexpected issues in implementation summary
|
||||
@@ -876,6 +909,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
- **Residual Risk:** MEDIUM - requires cultural change
|
||||
|
||||
**Risk Mitigation Strategy:**
|
||||
|
||||
- Phased rollout: Test with subset of developers first (if possible)
|
||||
- Clear communication: Explain WHY blocking is important
|
||||
- Support: Troubleshooting guide and quick-check tasks
|
||||
@@ -898,10 +932,12 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
**Total Estimated Time:** 3-4 hours (excluding Phase 6)
|
||||
|
||||
**Critical Path:**
|
||||
|
||||
- Phase 1 → Phase 4 (must verify blocking works)
|
||||
- Phase 4 → Phase 5 (documentation depends on successful testing)
|
||||
|
||||
**Parallel Work Possible:**
|
||||
|
||||
- Phase 2 can start while Phase 1 is being tested
|
||||
- Phase 3 documentation can be drafted during Phase 1-2
|
||||
|
||||
@@ -945,6 +981,7 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
- **Alternative Rejected:** Full golangci-lint (30-60s too slow)
|
||||
|
||||
**Review Conditions:**
|
||||
|
||||
- Re-evaluate after 1 month of usage
|
||||
- Gather developer feedback on performance and adoption
|
||||
- Measure impact on commit frequency and quality
|
||||
@@ -955,12 +992,15 @@ Move `docs/plans/current_spec.md` to `docs/plans/archive/staticcheck_blocking_in
|
||||
## Archive Location
|
||||
|
||||
**Current Specification:**
|
||||
|
||||
- This file: `docs/plans/current_spec.md`
|
||||
|
||||
**After Implementation:**
|
||||
|
||||
- Archive to: `docs/plans/archive/staticcheck_blocking_integration_2026-01-11.md`
|
||||
|
||||
**Previous Specifications:**
|
||||
|
||||
- See: [docs/plans/archive/](archive/) for historical specs
|
||||
|
||||
---
|
||||
|
||||
@@ -33,6 +33,7 @@ PR Opened
|
||||
**Architecture Decision**: Keep workflows separate with dependency orchestration via `workflow_run` trigger.
|
||||
|
||||
**Rationale**:
|
||||
|
||||
- **Modularity**: Each workflow has a distinct, cohesive purpose
|
||||
- **Reusability**: Verification can run on-demand or scheduled independently
|
||||
- **Maintainability**: Easier to test, debug, and understand individual workflows
|
||||
@@ -45,6 +46,7 @@ PR Opened
|
||||
Modify `supply-chain-verify.yml` triggers:
|
||||
|
||||
**Current**:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
release:
|
||||
@@ -57,6 +59,7 @@ on:
|
||||
```
|
||||
|
||||
**Proposed**:
|
||||
|
||||
```yaml
|
||||
on:
|
||||
release:
|
||||
@@ -77,6 +80,7 @@ on:
|
||||
```
|
||||
|
||||
**Key Changes**:
|
||||
|
||||
1. Remove `pull_request` trigger (prevents premature execution)
|
||||
2. Add `workflow_run` trigger that waits for docker-build workflow
|
||||
3. Specify branches to match docker-build's branch targets
|
||||
@@ -164,6 +168,7 @@ Update the "Comment on PR" step to work with `workflow_run` context:
|
||||
### Workflow Execution Flow (After Fix)
|
||||
|
||||
**PR Workflow**:
|
||||
|
||||
```
|
||||
PR Opened/Updated
|
||||
└─> docker-build.yml runs
|
||||
@@ -179,6 +184,7 @@ PR Opened/Updated
|
||||
```
|
||||
|
||||
**Push to Main**:
|
||||
|
||||
```
|
||||
Push to main
|
||||
└─> docker-build.yml runs
|
||||
@@ -190,12 +196,14 @@ Push to main
|
||||
### Implementation Checklist
|
||||
|
||||
**Changes to `.github/workflows/supply-chain-verify.yml`**:
|
||||
|
||||
- [x] Update triggers section (remove pull_request, add workflow_run)
|
||||
- [x] Add job conditional (check workflow_run.conclusion)
|
||||
- [x] Update tag determination (handle workflow_run context)
|
||||
- [x] Update PR comment logic (extract PR number correctly)
|
||||
|
||||
**Testing Plan**:
|
||||
|
||||
- [ ] Test PR workflow (verify sequential execution and correct tagging)
|
||||
- [ ] Test push to main (verify 'latest' tag usage)
|
||||
- [ ] Test manual trigger (verify workflow_dispatch works)
|
||||
@@ -247,6 +255,7 @@ Push to main
|
||||
**Status**: ✅ All phases completed successfully
|
||||
|
||||
**Changes Made**:
|
||||
|
||||
1. ✅ Added `workflow_run` trigger to supply-chain-verify.yml
|
||||
2. ✅ Removed `pull_request` trigger
|
||||
3. ✅ Added workflow success filter
|
||||
@@ -255,12 +264,14 @@ Push to main
|
||||
6. ✅ Added debug logging for validation
|
||||
|
||||
**Validation**:
|
||||
|
||||
- ✅ Security audit passed (see [qa_report_workflow_orchestration.md](../../reports/qa_report_workflow_orchestration.md))
|
||||
- ✅ Pre-commit hooks passed
|
||||
- ✅ YAML syntax validated
|
||||
- ✅ No breaking changes to other workflows
|
||||
|
||||
**Documentation**:
|
||||
|
||||
- [Implementation Summary](../../implementation/WORKFLOW_ORCHESTRATION_FIX.md)
|
||||
- [QA Report](../../reports/qa_report_workflow_orchestration.md)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user