@@ -47,17 +47,21 @@ jobs:
4747 deployments : write
4848 security-events : write
4949
50- # If scan failed, bump tag and rebuild the image
51- bump-tag :
50+ # If scan failed, compute next version (dry run) and attempt a rebuild.
51+ # The tag is only created after a successful rebuild to prevent
52+ # infinite bump loops when a CVE fix requires a major version upgrade
53+ # that a simple rebuild cannot provide.
54+ compute-next-version :
5255 needs : periodic-scan
5356 runs-on : ubuntu-latest
5457 if : ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' }}
5558 steps :
56- - name : Bump version and push tag
59+ - name : Compute next version (dry run — no tag created)
5760 id : tag_version
5861 uses : mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b # v6.2
5962 with :
6063 github_token : ${{ secrets.GITHUB_TOKEN }}
64+ dry_run : true
6165 - name : Parse new version
6266 id : parsed
6367 uses : booxmedialtd/ws-action-parse-semver@7784200024d6b3fc01253e617ec0168daf603de3 # v1.4.7
@@ -68,19 +72,85 @@ jobs:
6872 new_version : ${{ steps.tag_version.outputs.new_version }}
6973 new_major_minor : ${{ steps.parsed.outputs.major }}.${{ steps.parsed.outputs.minor }}
7074 permissions :
71- contents : write
72- deployments : write
73- security-events : write
75+ contents : read
7476
7577 update-image :
76- needs : [get-image-reference, periodic-scan, bump-tag ]
78+ needs : [get-image-reference, periodic-scan, compute-next-version ]
7779 if : ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' }}
7880 uses : " ./.github/workflows/docker_build.yml"
7981 with :
80- REF_TO_CHECKOUT : ${{ needs.bump-tag .outputs.new_tag }}
81- IMAGE_REFERENCES : " ${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.bump-tag .outputs.new_version }},${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.bump-tag .outputs.new_major_minor }}"
82+ REF_TO_CHECKOUT : ${{ needs.get-image-reference .outputs.image_tag }}
83+ IMAGE_REFERENCES : " ${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.compute-next-version .outputs.new_version }},${{ needs.get-image-reference.outputs.image_repo }}:${{ needs.compute-next-version .outputs.new_major_minor }}"
8284 permissions :
8385 contents : read
8486 deployments : write
8587 security-events : write
8688 packages : write
89+
90+ # Only create the git tag after the rebuilt image passes Trivy and is pushed
91+ create-tag :
92+ needs : [periodic-scan, update-image]
93+ runs-on : ubuntu-latest
94+ if : ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' && needs.update-image.result == 'success' }}
95+ steps :
96+ - name : Bump version and push tag
97+ uses : mathieudutour/github-tag-action@a22cf08638b34d5badda920f9daf6e72c477b07b # v6.2
98+ with :
99+ github_token : ${{ secrets.GITHUB_TOKEN }}
100+ permissions :
101+ contents : write
102+
103+ # If the rebuild still has vulnerabilities, open a GitHub issue for manual triage
104+ # instead of looping endlessly
105+ alert-on-failure :
106+ needs : [periodic-scan, update-image]
107+ runs-on : ubuntu-latest
108+ if : ${{ !cancelled() && needs.periodic-scan.outputs.trivy_conclusion == 'failure' && needs.update-image.result == 'failure' }}
109+ permissions :
110+ issues : write
111+ steps :
112+ - name : Check for existing open issue
113+ id : check_issue
114+ uses : actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
115+ with :
116+ script : |
117+ const issues = await github.rest.issues.listForRepo({
118+ owner: context.repo.owner,
119+ repo: context.repo.repo,
120+ state: 'open',
121+ labels: 'trivy,security',
122+ per_page: 1
123+ });
124+ return issues.data.length > 0 ? 'true' : 'false';
125+ result-encoding : string
126+
127+ - name : Create GitHub issue for unresolved vulnerabilities
128+ if : steps.check_issue.outputs.result == 'false'
129+ uses : actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
130+ with :
131+ script : |
132+ await github.rest.issues.create({
133+ owner: context.repo.owner,
134+ repo: context.repo.repo,
135+ title: 'Trivy: unresolved container vulnerabilities after rebuild',
136+ body: [
137+ '## Summary',
138+ '',
139+ 'The daily Trivy periodic scan found Critical/High vulnerabilities in the latest published Docker image.',
140+ 'An automated rebuild was attempted but the rebuilt image **still has vulnerabilities**,',
141+ 'indicating the fix requires a manual dependency update rather than a base image refresh.',
142+ '',
143+ '## Next steps',
144+ '',
145+ '- Review findings in the [Security tab](../security/code-scanning)',
146+ '- Update the affected dependencies to a version that includes the fix',
147+ '- Or add the CVE ID(s) to a `.trivyignore` file if the risk is accepted',
148+ '',
149+ '## Details',
150+ '',
151+ `- **Workflow run:** ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,
152+ `- **Triggered at:** ${new Date().toISOString()}`,
153+ ].join('\n'),
154+ labels: ['trivy', 'security']
155+ });
156+
0 commit comments