Skip to content

Commit 43c6b83

Browse files
committed
changes for common docker build
Signed-off-by: Vipin Yadav <vipin.yadav@progress.com>
1 parent 645ede7 commit 43c6b83

File tree

4 files changed

+345
-104
lines changed

4 files changed

+345
-104
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# build-docker-image.yml
2+
# Reusable workflow to build a Docker image and upload it as an artifact.
3+
# Supports three build strategies:
4+
# 1. build-docker.sh script (e.g., dsm-erchef)
5+
# 2. Makefile with compose-build target
6+
# 3. Standard docker build (fallback)
7+
#
8+
# The built image is saved as a tar and uploaded as a GitHub Actions artifact
9+
# for downstream jobs (e.g., Wiz CLI scan, Grype scan) to consume.
10+
11+
name: Build Docker image
12+
13+
on:
14+
workflow_call:
15+
inputs:
16+
skip-aws:
17+
description: 'Skip AWS ECR login (for repos that do not need ECR base images)'
18+
required: false
19+
type: boolean
20+
default: false
21+
outputs:
22+
image-names:
23+
description: 'Space-separated list of built Docker image names (repository:tag)'
24+
value: ${{ jobs.build.outputs.image-names }}
25+
26+
jobs:
27+
build:
28+
name: Build and upload Docker image
29+
runs-on: ubuntu-latest
30+
permissions:
31+
id-token: write
32+
contents: read
33+
outputs:
34+
image-names: ${{ steps.build-image.outputs.IMAGES }}
35+
steps:
36+
- name: Checkout repository
37+
uses: actions/checkout@v6
38+
with:
39+
fetch-depth: 0
40+
41+
- name: Configure git for private repos
42+
run: git config --global url."https://${{ secrets.GH_TOKEN }}@github.com/".insteadOf "https://github.com/"
43+
44+
- name: Configure AWS credentials
45+
uses: aws-actions/configure-aws-credentials@v4
46+
if: ${{ !inputs.skip-aws }}
47+
with:
48+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
49+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
50+
aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }}
51+
aws-region: us-east-2
52+
53+
- name: Login to Amazon ECR
54+
id: login-ecr
55+
if: ${{ !inputs.skip-aws }}
56+
uses: aws-actions/amazon-ecr-login@v2
57+
58+
- name: Build Docker image
59+
id: build-image
60+
env:
61+
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
62+
run: |
63+
if [ ! -f "Dockerfile" ]; then
64+
echo "❌ No Dockerfile found - cannot build"
65+
exit 1
66+
fi
67+
68+
echo "Building Docker image..."
69+
REPO_NAME=$(basename $(pwd))
70+
71+
# Strategy 1: Check for build-docker.sh script (e.g., dsm-erchef)
72+
if [ -f "build-docker.sh" ]; then
73+
echo "Found build-docker.sh script - using it to build images"
74+
chmod +x build-docker.sh
75+
GITHUB_TOKEN="${{ secrets.GH_TOKEN }}" ./build-docker.sh
76+
77+
# Detect all images built (typically repo name or repo-name-init)
78+
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -E "^${REPO_NAME}" | grep -v "^<none>")
79+
80+
if [ -z "$IMAGES" ]; then
81+
echo "⚠️ No images found with prefix ${REPO_NAME} after build-docker.sh"
82+
echo "Checking for any recently built images..."
83+
IMAGES=$(docker images --format "{{.CreatedAt}}\t{{.Repository}}:{{.Tag}}" | sort -r | head -5 | cut -f2 | grep -v "^<none>")
84+
fi
85+
# Strategy 2: Check for Makefile with compose-build target (e.g., chef-platform-user-accounts-service)
86+
elif [ -f "Makefile" ] && grep -q "^compose-build:" Makefile; then
87+
echo "Using Makefile compose-build target with GITHUB_TOKEN"
88+
export GITHUB_TOKEN="${{ secrets.GH_TOKEN }}"
89+
make compose-build
90+
91+
echo "Detecting built images..."
92+
# Get all image names from compose, then keep only ones that exist locally (i.e., were actually built)
93+
IMAGES=""
94+
for img in $(docker compose config --images 2>/dev/null | sort -u); do
95+
TAG_IMG=$(echo "$img" | grep -q ':' && echo "$img" || echo "${img}:latest")
96+
if docker image inspect "$TAG_IMG" &>/dev/null; then
97+
IMAGES="${IMAGES}${TAG_IMG} "
98+
fi
99+
done
100+
IMAGES=$(echo "$IMAGES" | xargs)
101+
102+
if [ -z "$IMAGES" ]; then
103+
echo "⚠️ Could not detect built images from compose config, falling back to repo name match"
104+
IMAGES=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${REPO_NAME}" | grep -v "^<none>")
105+
fi
106+
# Strategy 3: Fallback to standard docker build
107+
else
108+
echo "Using standard docker build with GITHUB_TOKEN build arg"
109+
docker build --build-arg GITHUB_TOKEN="${{ secrets.GH_TOKEN }}" -t "${REPO_NAME}:latest" .
110+
IMAGES="${REPO_NAME}:latest"
111+
fi
112+
113+
if [ -z "$IMAGES" ]; then
114+
echo "❌ No Docker images found after build"
115+
exit 1
116+
fi
117+
118+
echo "Found images:"
119+
echo "$IMAGES"
120+
121+
# Output as space-separated list for downstream jobs
122+
echo "IMAGES=$(echo $IMAGES | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
123+
124+
- name: Save Docker images to tar
125+
run: |
126+
IMAGES="${{ steps.build-image.outputs.IMAGES }}"
127+
echo "Saving images to /tmp/docker-image.tar: $IMAGES"
128+
docker save $IMAGES -o /tmp/docker-image.tar
129+
ls -lh /tmp/docker-image.tar
130+
131+
- name: Upload Docker image artifact
132+
uses: actions/upload-artifact@v4
133+
with:
134+
name: docker-image-for-scans
135+
path: /tmp/docker-image.tar
136+
retention-days: 1

.github/workflows/ci-main-pull-request.yml

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ on:
156156
required: false
157157
type: boolean
158158
default: false
159-
grype-image-skip-aws:
160-
description: 'Skip Grype image scan on AWS ECR images to avoid rate limits (assumes these images are scanned with Amazon ECR scan or Trivy)'
159+
image-skip-aws:
160+
description: 'Skip AWS ECR login for Docker image scans (for repos that do not need ECR base images)'
161161
required: false
162162
type: boolean
163163
default: false
@@ -1000,22 +1000,36 @@ jobs:
10001000
name: 'Grype Docker image scan'
10011001
if: ${{ inputs.perform-grype-image-scan }}
10021002
uses: chef/common-github-actions/.github/workflows/grype.yml@main
1003-
needs: checkout
1003+
needs: [checkout, build-docker-image]
10041004
secrets: inherit
10051005
with:
10061006
fail-grype-on-high: ${{ inputs.grype-image-fail-on-high }}
10071007
fail-grype-on-critical: ${{ inputs.grype-image-fail-on-critical }}
1008-
grype-image-skip-aws: ${{ inputs.grype-image-skip-aws }}
1008+
grype-image-skip-aws: ${{ inputs.image-skip-aws }}
1009+
prebuilt-image-artifact: docker-image-for-scans
1010+
prebuilt-image-names: ${{ needs.build-docker-image.outputs.image-names }}
1011+
1012+
build-docker-image:
1013+
name: 'Build Docker image for security scans'
1014+
if: ${{ inputs.perform-grype-image-scan == true || inputs.perform-wiz-scan == true }}
1015+
uses: chef/common-github-actions/.github/workflows/build-docker-image.yml@main
1016+
needs: checkout
1017+
secrets: inherit
1018+
with:
1019+
skip-aws: ${{ inputs.image-skip-aws }}
10091020

10101021
run-wiz-scan:
10111022
name: 'Wiz CLI security scan'
10121023
if: ${{ inputs.perform-wiz-scan == true }}
1013-
uses: chef/common-github-actions/.github/workflows/wiz.yml@grype-wiz
1014-
needs: checkout
1024+
uses: chef/common-github-actions/.github/workflows/wiz.yml@main
1025+
needs: [checkout, build-docker-image]
10151026
with:
10161027
fail-build: ${{ inputs.wiz-fail-build }}
10171028
fail-on-critical: ${{ inputs.wiz-fail-on-critical }}
10181029
fail-on-high: ${{ inputs.wiz-fail-on-high }}
1030+
wiz-image-skip-aws: ${{ inputs.image-skip-aws }}
1031+
prebuilt-image-artifact: docker-image-for-scans
1032+
prebuilt-image-names: ${{ needs.build-docker-image.outputs.image-names }}
10191033
secrets: inherit
10201034

10211035
run-grype-hab-package-scan:
@@ -1159,14 +1173,6 @@ jobs:
11591173
# VER=$(cat VERSION)
11601174
# echo "VERSION=$VER" >> $GITHUB_ENV
11611175
# then ${{ env.VERSION }}
1162-
1163-
run-wiz-scan:
1164-
name: 'Wiz CLI security scan'
1165-
if: ${{ inputs.perform-wiz-scan == true }}
1166-
uses: chef/common-github-actions/.github/workflows/wiz.yml@main
1167-
with:
1168-
fail-build: ${{ inputs.wiz-fail-build }}
1169-
secrets: inherit
11701176

11711177
set-application-version:
11721178
runs-on: ubuntu-latest

.github/workflows/grype.yml

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ on:
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

2636
jobs:
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

Comments
 (0)