2222 required : false
2323 type : boolean
2424 default : false
25+ prebuilt-image-artifact :
26+ description : ' Name of uploaded artifact containing a Docker image tar (skip Docker build if provided)'
27+ required : false
28+ type : string
29+ default : ' '
30+ prebuilt-image-names :
31+ description : ' Space-separated list of Docker image:tag names inside the prebuilt artifact tar'
32+ required : false
33+ type : string
34+ default : ' '
2535
2636jobs :
2737 grype-scan :
@@ -65,13 +75,29 @@ jobs:
6575 if : ${{ !inputs.grype-image-skip-aws }}
6676 uses : aws-actions/amazon-ecr-login@v2
6777
68- - name : Scan with Grype
69- id : grype-scan
78+ - name : Download prebuilt Docker image
79+ if : ${{ inputs.prebuilt-image-artifact != '' }}
80+ uses : actions/download-artifact@v4
81+ with :
82+ name : ${{ inputs.prebuilt-image-artifact }}
83+ path : /tmp
84+
85+ - name : Load prebuilt Docker image
86+ id : load-image
87+ if : ${{ inputs.prebuilt-image-artifact != '' }}
88+ run : |
89+ echo "Loading prebuilt images from artifact..."
90+ docker load -i /tmp/docker-image.tar
91+ echo "IMAGES=${{ inputs.prebuilt-image-names }}" >> "$GITHUB_OUTPUT"
92+ echo "Loaded images: ${{ inputs.prebuilt-image-names }}"
93+ docker images
94+
95+ - name : Build Docker image
96+ id : build-image
97+ if : ${{ inputs.prebuilt-image-artifact == '' }}
7098 env :
7199 GITHUB_TOKEN : ${{ secrets.GH_TOKEN }}
72100 run : |
73- SCAN_NAME="${{ github.repository }}"
74-
75101 if [ ! -f "Dockerfile" ]; then
76102 echo "❌ No Dockerfile found - this workflow requires a Dockerfile to scan Docker image"
77103 exit 1
@@ -101,13 +127,19 @@ jobs:
101127 make compose-build
102128
103129 echo "Detecting built images..."
104- docker compose images
105-
106- IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${REPO_NAME}" | grep -v "^<none>")
130+ # Get all image names from compose, then keep only ones that exist locally (i.e., were actually built)
131+ IMAGES=""
132+ for img in $(docker compose config --images 2>/dev/null | sort -u); do
133+ TAG_IMG=$(echo "$img" | grep -q ':' && echo "$img" || echo "${img}:latest")
134+ if docker image inspect "$TAG_IMG" &>/dev/null; then
135+ IMAGES="${IMAGES}${TAG_IMG} "
136+ fi
137+ done
138+ IMAGES=$(echo "$IMAGES" | xargs)
107139
108140 if [ -z "$IMAGES" ]; then
109- echo "No images found with prefix ${REPO_NAME}, scanning all recent images "
110- IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "^<none>" | head -5 )
141+ echo "⚠️ Could not detect built images from compose config, falling back to repo name match "
142+ IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${REPO_NAME}" | grep -v "^<none>")
111143 fi
112144 # Strategy 3: Fallback to standard docker build
113145 else
@@ -121,6 +153,28 @@ jobs:
121153 exit 1
122154 fi
123155
156+ echo "IMAGES=$(echo $IMAGES | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
157+ echo "Found images: $IMAGES"
158+
159+ - name : Determine scan targets
160+ id : scan-target
161+ run : |
162+ IMAGES="${{ steps.load-image.outputs.IMAGES || steps.build-image.outputs.IMAGES }}"
163+ if [ -z "$IMAGES" ]; then
164+ echo "❌ No images available to scan"
165+ exit 1
166+ fi
167+ echo "IMAGES=$IMAGES" >> "$GITHUB_OUTPUT"
168+ echo "Scan targets: $IMAGES"
169+
170+ - name : Scan with Grype
171+ id : grype-scan
172+ env :
173+ GITHUB_TOKEN : ${{ secrets.GH_TOKEN }}
174+ run : |
175+ SCAN_NAME="${{ github.repository }}"
176+ IMAGES="${{ steps.scan-target.outputs.IMAGES }}"
177+
124178 echo "Found images to scan:"
125179 echo "$IMAGES"
126180
0 commit comments