Skip to content

Commit 8ec3bdd

Browse files
cconrad8linglpLingling PengLingling PengBryanFauble
authored
Remove sorting functionality (#1358)
* [SYNPY-1798]: updated black to 26.3.1 and reran pre-commit (#1341) * update black to 26.3.1 and rerun pre-commit * update the tutorial line --------- Co-authored-by: Lingling Peng <lpeng@w290.local> Co-authored-by: Lingling Peng <lpeng@Mac.SageCorpWiFi> * [SYNPY-1764] Add Trivy container vulnerability scanning (#1346) * [SYNPY-1764] Add Trivy container vulnerability scanning to Docker build Add Trivy scanning to gate Docker image publication on GHCR. Both release and develop Docker jobs now follow a build→scan→push pattern where images are only pushed if no Critical/High unfixed vulnerabilities are found. New workflows: - trivy.yml: reusable Trivy scanning workflow with SARIF upload to GitHub Security tab - docker_build.yml: reusable build/scan/push workflow for image rebuilds - trivy_periodic_scan.yml: daily rescan of latest published image with auto-remediation * Address PR review feedback from linglp and jaymedina - Fix push jobs to load scanned tar instead of rebuilding (build.yml) - Pin trivy-action to SHA for v0.35.0 to address supply chain attack - Fix env.repo_name output using $GITHUB_OUTPUT (trivy_periodic_scan.yml) - Pin all third-party actions to commit SHAs - Remove unnecessary permissions on get-image-reference job - Use !cancelled() for SARIF upload condition (trivy.yml) - Use LOCAL_IMAGE_TAG env var instead of hardcoded string (docker_build.yml) - Fix IMAGE_REFERENCES YAML line continuation * Prevent infinite rebuild loop in periodic Trivy scan Restructure trivy_periodic_scan.yml so the git tag is only created after a successful rebuild (not before). If the rebuild still has vulnerabilities, a GitHub issue is opened for manual triage instead of looping endlessly. - Rename bump-tag → compute-next-version (dry_run: true) - Add create-tag job gated on update-image success - Add alert-on-failure job that opens a GitHub issue with duplicate prevention when remediation fails * pre-commit * Update Trivy scan workflow to use previous tag and adjust image references * Address PR review feedback - Pin codeql-action/upload-sarif to SHA and upgrade to v3.35.1 - Guard update-image job on compute-next-version success - Use absolute URL for Security tab link in auto-created issues * Add actions read permission for Trivy scan job (#1355) * Add optional ARTIFACT_NAME_SUFFIX input to Trivy workflow and update artifact naming (#1357) * remove sort --------- Co-authored-by: Lingling <55448354+linglp@users.noreply.github.com> Co-authored-by: Lingling Peng <lpeng@w290.local> Co-authored-by: Lingling Peng <lpeng@Mac.SageCorpWiFi> Co-authored-by: BryanFauble <17128019+BryanFauble@users.noreply.github.com>
1 parent 693d01b commit 8ec3bdd

87 files changed

Lines changed: 3518 additions & 2386 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 143 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -552,87 +552,186 @@ jobs:
552552
exit 1
553553
554554
# containerize the package and upload to the GHCR upon new release (whether pre-release or not)
555-
ghcr-build-and-push-on-release:
555+
# Step 1: Build the Docker image and save as tar for scanning
556+
ghcr-build-on-release:
556557
needs: deploy
557558
runs-on: ubuntu-latest
558559
permissions:
559560
contents: read
560561
packages: write
562+
outputs:
563+
image-tags: ${{ steps.set-tags.outputs.tags }}
564+
image-name: synapsepythonclient-release
565+
env:
566+
TARFILE_NAME: synapsepythonclient-release.tar
561567

562568
steps:
563569
- name: Check out the repo
564570
uses: actions/checkout@v4
565571
- name: Extract Release Version
566572
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
567573
shell: bash
574+
- name: Set image tags
575+
id: set-tags
576+
shell: bash
577+
run: |
578+
if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then
579+
echo "tags=ghcr.io/sage-bionetworks/synapsepythonclient:${{ env.RELEASE_VERSION }}-prerelease" >> $GITHUB_OUTPUT
580+
else
581+
echo "tags=ghcr.io/sage-bionetworks/synapsepythonclient:latest,ghcr.io/sage-bionetworks/synapsepythonclient:${{ env.RELEASE_VERSION }}" >> $GITHUB_OUTPUT
582+
fi
568583
- name: Set up Docker Buildx
569584
uses: docker/setup-buildx-action@v2
570-
- name: Log in to GitHub Container Registry
571-
uses: docker/login-action@v2
572-
with:
573-
registry: ghcr.io
574-
username: ${{ github.actor }}
575-
password: ${{ secrets.GITHUB_TOKEN }}
576-
- name: Build and push Docker image (official release)
577-
id: docker_build
578-
if: '!github.event.release.prerelease'
579-
uses: docker/build-push-action@v3
585+
- name: Build Docker image
586+
uses: docker/build-push-action@v5
580587
with:
581-
push: true
588+
context: .
589+
push: false
590+
load: true
582591
provenance: false
583-
tags: ghcr.io/sage-bionetworks/synapsepythonclient:latest,ghcr.io/sage-bionetworks/synapsepythonclient:${{ env.RELEASE_VERSION }}
592+
tags: synapsepythonclient-release:local
584593
file: ./Dockerfile
585594
platforms: linux/amd64
586595
cache-from: type=registry,ref=ghcr.io/sage-bionetworks/synapsepythonclient:build-cache
587-
cache-to: type=registry,mode=max,ref=ghcr.io/sage-bionetworks/synapsepythonclient:build-cache
588-
- name: Build and push Docker image (pre-release)
589-
id: docker_build_prerelease
590-
if: 'github.event.release.prerelease'
591-
uses: docker/build-push-action@v3
596+
cache-to: type=inline
597+
- name: Save Docker image to tar
598+
run: docker save synapsepythonclient-release:local -o ${{ env.TARFILE_NAME }}
599+
- name: Upload tar artifact
600+
uses: actions/upload-artifact@v4
592601
with:
593-
push: true
594-
provenance: false
595-
tags: ghcr.io/sage-bionetworks/synapsepythonclient:${{ env.RELEASE_VERSION }}-prerelease
596-
file: ./Dockerfile
597-
platforms: linux/amd64
598-
cache-from: type=registry,ref=ghcr.io/sage-bionetworks/synapsepythonclient:build-cache-prerelease
599-
cache-to: type=registry,mode=max,ref=ghcr.io/sage-bionetworks/synapsepythonclient:build-cache-prerelease
600-
- name: Output image digest (official release)
601-
if: '!github.event.release.prerelease'
602-
run: echo "The image digest for official release is ${{ steps.docker_build.outputs.digest }}"
603-
- name: Output image digest (pre-release)
604-
if: 'github.event.release.prerelease'
605-
run: echo "The image digest for pre-release is ${{ steps.docker_build_prerelease.outputs.digest }}"
602+
name: ${{ env.TARFILE_NAME }}
603+
path: ${{ env.TARFILE_NAME }}
604+
retention-days: 1
605+
606+
# Step 2: Scan the built image with Trivy before pushing
607+
trivy-scan-release:
608+
needs: [ghcr-build-on-release]
609+
uses: ./.github/workflows/trivy.yml
610+
with:
611+
SOURCE_TYPE: tar
612+
TARFILE_NAME: synapsepythonclient-release.tar
613+
IMAGE_NAME: synapsepythonclient-release:local
614+
EXIT_CODE: 1
615+
permissions:
616+
contents: read
617+
security-events: write
618+
actions: read
606619

607-
# containerize the package and upload to the GHCR upon commit in develop
608-
ghcr-build-and-push-on-develop:
620+
# Step 3: Push the image to GHCR only if Trivy scan passes
621+
ghcr-push-on-release:
622+
needs: [ghcr-build-on-release, trivy-scan-release]
609623
runs-on: ubuntu-latest
610-
if: github.ref == 'refs/heads/develop'
611624
permissions:
612625
contents: read
613626
packages: write
614627

628+
env:
629+
TARFILE_NAME: synapsepythonclient-release.tar
630+
615631
steps:
616-
- name: Check out the repo
617-
uses: actions/checkout@v4
618-
- name: Set up Docker Buildx
619-
uses: docker/setup-buildx-action@v2
632+
- name: Download scanned tar
633+
uses: actions/download-artifact@v4
634+
with:
635+
name: ${{ env.TARFILE_NAME }}
636+
path: /tmp
637+
- name: Load Docker image from tar
638+
run: docker load -i /tmp/${{ env.TARFILE_NAME }}
620639
- name: Log in to GitHub Container Registry
621640
uses: docker/login-action@v2
622641
with:
623642
registry: ghcr.io
624643
username: ${{ github.actor }}
625644
password: ${{ secrets.GITHUB_TOKEN }}
626-
- name: Build and push Docker image for develop
627-
id: docker_build
645+
- name: Tag and push Docker image
646+
shell: bash
647+
run: |
648+
IFS=',' read -ra TAGS <<< "${{ needs.ghcr-build-on-release.outputs.image-tags }}"
649+
for TAG in "${TAGS[@]}"; do
650+
docker tag synapsepythonclient-release:local "$TAG"
651+
docker push "$TAG"
652+
done
653+
654+
# containerize the package and upload to the GHCR upon commit in develop
655+
# Step 1: Build the Docker image and save as tar for scanning
656+
ghcr-build-on-develop:
657+
runs-on: ubuntu-latest
658+
if: github.ref == 'refs/heads/develop'
659+
permissions:
660+
contents: read
661+
packages: write
662+
outputs:
663+
image-tag: ghcr.io/sage-bionetworks/synapsepythonclient:develop-${{ github.sha }}
664+
image-name: synapsepythonclient-develop
665+
env:
666+
TARFILE_NAME: synapsepythonclient-develop.tar
667+
668+
steps:
669+
- name: Check out the repo
670+
uses: actions/checkout@v4
671+
- name: Set up Docker Buildx
672+
uses: docker/setup-buildx-action@v2
673+
- name: Build Docker image
628674
uses: docker/build-push-action@v5
629675
with:
630-
push: true
676+
context: .
677+
push: false
678+
load: true
631679
provenance: false
632-
tags: ghcr.io/sage-bionetworks/synapsepythonclient:develop-${{ github.sha }}
680+
tags: synapsepythonclient-develop:local
633681
file: ./Dockerfile
634682
platforms: linux/amd64
635683
cache-from: type=registry,ref=ghcr.io/sage-bionetworks/synapsepythonclient:build-cache
636684
cache-to: type=inline
637-
- name: Output image digest
638-
run: echo "The image digest is ${{ steps.docker_build.outputs.digest }}"
685+
- name: Save Docker image to tar
686+
run: docker save synapsepythonclient-develop:local -o ${{ env.TARFILE_NAME }}
687+
- name: Upload tar artifact
688+
uses: actions/upload-artifact@v4
689+
with:
690+
name: ${{ env.TARFILE_NAME }}
691+
path: ${{ env.TARFILE_NAME }}
692+
retention-days: 1
693+
694+
# Step 2: Scan the built image with Trivy before pushing
695+
trivy-scan-develop:
696+
needs: [ghcr-build-on-develop]
697+
uses: ./.github/workflows/trivy.yml
698+
with:
699+
SOURCE_TYPE: tar
700+
TARFILE_NAME: synapsepythonclient-develop.tar
701+
IMAGE_NAME: synapsepythonclient-develop:local
702+
EXIT_CODE: 1
703+
permissions:
704+
contents: read
705+
security-events: write
706+
actions: read
707+
708+
# Step 3: Push the image to GHCR only if Trivy scan passes
709+
ghcr-push-on-develop:
710+
needs: [ghcr-build-on-develop, trivy-scan-develop]
711+
runs-on: ubuntu-latest
712+
if: github.ref == 'refs/heads/develop'
713+
permissions:
714+
contents: read
715+
packages: write
716+
717+
env:
718+
TARFILE_NAME: synapsepythonclient-develop.tar
719+
720+
steps:
721+
- name: Download scanned tar
722+
uses: actions/download-artifact@v4
723+
with:
724+
name: ${{ env.TARFILE_NAME }}
725+
path: /tmp
726+
- name: Load Docker image from tar
727+
run: docker load -i /tmp/${{ env.TARFILE_NAME }}
728+
- name: Log in to GitHub Container Registry
729+
uses: docker/login-action@v2
730+
with:
731+
registry: ghcr.io
732+
username: ${{ github.actor }}
733+
password: ${{ secrets.GITHUB_TOKEN }}
734+
- name: Tag and push Docker image
735+
run: |
736+
docker tag synapsepythonclient-develop:local "${{ needs.ghcr-build-on-develop.outputs.image-tag }}"
737+
docker push "${{ needs.ghcr-build-on-develop.outputs.image-tag }}"

.github/workflows/docker_build.yml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
---
2+
#
3+
# Reusable workflow to build, scan, and push a Docker image.
4+
# Called by the periodic scan workflow to rebuild images
5+
# when new vulnerabilities are found.
6+
#
7+
name: Build and publish a Docker image
8+
9+
on:
10+
workflow_call:
11+
inputs:
12+
REF_TO_CHECKOUT:
13+
required: false
14+
type: string
15+
description: "Reference to checkout, e.g. a tag like v1.0.1. Defaults to the branch/tag of the current event."
16+
IMAGE_REFERENCES:
17+
required: true
18+
type: string
19+
description: "Comma-separated image references, e.g., ghcr.io/sage-bionetworks/synapsepythonclient:1.0.1"
20+
21+
env:
22+
TARFILE_NAME: image.tar
23+
LOCAL_IMAGE_TAG: rebuild-image:local
24+
25+
jobs:
26+
build:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v4
31+
with:
32+
ref: ${{ inputs.REF_TO_CHECKOUT }}
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v2
36+
37+
- name: Build Docker image
38+
uses: docker/build-push-action@v5
39+
with:
40+
context: .
41+
push: false
42+
load: true
43+
tags: ${{ env.LOCAL_IMAGE_TAG }}
44+
file: ./Dockerfile
45+
platforms: linux/amd64
46+
47+
- name: Save Docker image to tar
48+
run: docker save ${{ env.LOCAL_IMAGE_TAG }} -o ${{ env.TARFILE_NAME }}
49+
50+
- name: Upload tarball for use by Trivy job
51+
uses: actions/upload-artifact@v4
52+
with:
53+
name: ${{ env.TARFILE_NAME }}
54+
path: ${{ env.TARFILE_NAME }}
55+
retention-days: 1
56+
57+
outputs:
58+
tarfile_artifact: ${{ env.TARFILE_NAME }}
59+
60+
trivy-scan:
61+
needs: build
62+
uses: "./.github/workflows/trivy.yml"
63+
with:
64+
SOURCE_TYPE: tar
65+
IMAGE_NAME: rebuild-image:local
66+
TARFILE_NAME: ${{ needs.build.outputs.tarfile_artifact }}
67+
EXIT_CODE: 1
68+
ARTIFACT_NAME_SUFFIX: -rebuild
69+
permissions:
70+
contents: read
71+
security-events: write
72+
actions: read
73+
74+
push-image:
75+
needs: [build, trivy-scan]
76+
runs-on: ubuntu-latest
77+
permissions:
78+
contents: read
79+
packages: write
80+
steps:
81+
- name: Download tar artifact
82+
uses: actions/download-artifact@v4
83+
with:
84+
name: ${{ needs.build.outputs.tarfile_artifact }}
85+
path: /tmp
86+
87+
- name: Load Docker image from tar
88+
run: docker load -i /tmp/${{ needs.build.outputs.tarfile_artifact }}
89+
90+
- name: Login to GitHub Container Registry
91+
uses: docker/login-action@v2
92+
with:
93+
registry: ghcr.io
94+
username: ${{ github.actor }}
95+
password: ${{ secrets.GITHUB_TOKEN }}
96+
97+
- name: Tag and push Docker image
98+
shell: bash
99+
run: |
100+
IFS=',' read -ra TAGS <<< "${{ inputs.IMAGE_REFERENCES }}"
101+
for TAG in "${TAGS[@]}"; do
102+
docker tag ${{ env.LOCAL_IMAGE_TAG }} "$TAG"
103+
docker push "$TAG"
104+
done

0 commit comments

Comments
 (0)