Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
32071f7
add job build-and-cache
lisac Apr 15, 2025
352feea
update trivy job to use the previously-built image
lisac Apr 15, 2025
30f2a9c
update anchore scan to use the previously-built image
lisac Apr 15, 2025
8bebaee
update dockle job to use the previously-built image
lisac Apr 15, 2025
47b8168
remove check on disk space
lisac Apr 15, 2025
cdc863f
remove debugging around disk space
lisac Apr 15, 2025
b8e1fb4
fix outdated documentation link
lisac Apr 15, 2025
409afe0
Update .github/workflows/vulnerability-scans.yml
lisac Apr 17, 2025
ec4acfb
rename job: build-and-cache -> build
lisac Apr 17, 2025
f93ad60
fix order: check that the cache exists before we try to use it
lisac Apr 17, 2025
e615687
move the cache-hit check to earlier in the job
lisac Apr 17, 2025
0f0985e
(lint fix) specify the path associated with the key we want to look up
lisac Apr 17, 2025
8f1f396
oops. need to check out the repo in order to use the Makefile.
lisac Apr 17, 2025
b5d6823
skip the trivy and anchore scans (temporarily)
lisac Apr 17, 2025
a622e54
modify 'release-build' make command to allow for additional build flags
lisac Apr 17, 2025
1430fd4
simplify. remove logic for caching the buildx layers. reduce the task…
lisac Apr 17, 2025
95a8a18
experiment: don't checkout the repo unless we have to build the docke…
lisac Apr 17, 2025
057ebb1
specify 'fail-on-cache-miss: true' for the subsequent jobs that expec…
lisac Apr 17, 2025
3c71f76
Revert "experiment: don't checkout the repo unless we have to build t…
lisac Apr 17, 2025
e7e8072
refactor the steps for building and caching the image into a new comp…
lisac Apr 28, 2025
0c6fcc6
update the build-and-publish to use the new composite action
lisac Apr 28, 2025
d6367d6
limit concurrency for the build action
lisac Apr 28, 2025
111fff0
update value to one that is defined
lisac Apr 28, 2025
04c44e2
move concurrency configuration to the job level
lisac Apr 28, 2025
d770279
re-try enforcing concurrency limit
lisac Apr 28, 2025
39d9fb5
Merge branch 'main' into lisac/ci-vulnerability-scans-build-image-once
lisac May 2, 2025
35353a2
move container registry check into its own job; and run the build-and…
lisac May 2, 2025
e760275
(debugging) add a sleep, to make more apparent whether multiple insta…
lisac May 2, 2025
3a27d6a
fix syntax
lisac May 2, 2025
1d970fc
re-try fixing syntax
lisac May 2, 2025
ba457e9
set id-token to have write permission
lisac May 2, 2025
2e5552c
specify the github ref to checkout
lisac May 4, 2025
541e272
update description text of the composite action
lisac May 4, 2025
73e97a0
revert 2e5552c. ineffective.
lisac May 5, 2025
32333f3
fix format - EOF newline
lisac May 5, 2025
9fde625
move 'docker load' to the composite action
lisac May 8, 2025
c58be8b
retrieve the image from cache rather than just checking for a cache hit
lisac May 8, 2025
ec69330
fix syntax. was missing required property 'shell'
lisac May 8, 2025
d05c648
debug: if we call 'docker load' from the composite action, will the c…
lisac May 8, 2025
ca3da45
debug: observe the environment variables describing the version of th…
lisac May 8, 2025
3124e7f
debugging - check that we get a cache hit after saving the cache, and…
lisac May 9, 2025
cf38b58
create composite action for get-commit-hash, copying logic from build…
lisac May 9, 2025
82b68ff
update build-and-publish.yml to call the get-commit-hash composite ac…
lisac May 9, 2025
db0f928
fix concurrency group - github.ref will not be reliable, need to use …
lisac May 9, 2025
f4c816e
adjust a condition for readability and to be more exact
lisac May 9, 2025
ee98361
correct concurrency group to use hash instead of github.ref. in vulne…
lisac May 9, 2025
1cc95b8
debug: the subsequent jobs may need to explicitly run docker load
lisac May 9, 2025
800fe0b
fix syntax
lisac May 9, 2025
772ddd4
fix (id for steps need to be unique, within a workflow)
lisac May 9, 2025
e56d5fa
use existing Makefile command for getting the commit sha
lisac May 9, 2025
dc57850
remove debugging, update some descriptive properties (name, description)
lisac May 9, 2025
c211561
restore original code for getting the commit hash
lisac May 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/actions/build-release-candidate/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: 'Build release candidates'
description: 'Builds, caches, and loads the docker image'
inputs:
app_name:
description: 'Name of application'
outputs:
image_cache_key:
description: "Cache key for the .tar of the docker image"
value: ${{ steps.create-image-identifier.outputs.image }}

runs:
using: "composite"
steps:

- name: Create image identifier
id: create-image-identifier
run: |
IMAGE_NAME=$(make APP_NAME=${{ inputs.app_name }} release-image-name)
IMAGE_TAG=$(make release-image-tag)
echo "image=$IMAGE_NAME:$IMAGE_TAG" >> "$GITHUB_OUTPUT"
shell: bash

- name: Retrieve the image from cache
id: retrieve-image-from-cache
uses: actions/cache@v4
with:
path: /tmp/docker-image.tar
key: ${{ steps.create-image-identifier.outputs.image }}

- name: Build and tag Docker image
if: steps.retrieve-image-from-cache.outputs.cache-hit != 'true'
run: |
make APP_NAME=${{ inputs.app_name }} release-build
shell: bash

- name: Save Docker image
if: steps.retrieve-image-from-cache.outputs.cache-hit != 'true'
run: |
docker save ${{ steps.create-image-identifier.outputs.image }} > /tmp/docker-image.tar
shell: bash

- name: Cache Docker image
if: steps.retrieve-image-from-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: /tmp/docker-image.tar
key: ${{ steps.create-image-identifier.outputs.image }}

- name: Load the Docker image
run: |
docker load < /tmp/docker-image.tar
shell: bash
56 changes: 36 additions & 20 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ on:
outputs:
commit_hash:
description: The SHA that was built
value: ${{ jobs.get-commit-hash.outputs.commit_hash }}
value: ${{ jobs.check-image-already-published.outputs.commit_hash }}
workflow_dispatch:
inputs:
app_name:
Expand All @@ -28,41 +28,69 @@ on:
type: string

jobs:
get-commit-hash:
name: Get commit hash
check-image-already-published:
name: Check whether the image is already published
runs-on: ubuntu-latest

permissions:
contents: read
id-token: write

outputs:
commit_hash: ${{ steps.get-commit-hash.outputs.commit_hash }}
is_image_published: ${{ steps.check-image-published.outputs.is_image_published }}

steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}

- name: Get commit hash
id: get-commit-hash
- id: get-commit-hash
run: |
# HEAD should be the same as inputs.ref since we checked out inputs.ref
COMMIT_HASH=$(git rev-parse HEAD)
echo "Commit hash: $COMMIT_HASH"
echo "commit_hash=$COMMIT_HASH" >> "$GITHUB_OUTPUT"

- name: Set up Terraform
uses: ./.github/actions/setup-terraform

- name: Configure AWS credentials
uses: ./.github/actions/configure-aws-credentials
with:
app_name: ${{ inputs.app_name }}
environment: shared

- name: Check if image is already published
id: check-image-published
run: |
is_image_published=$(./bin/is-image-published "${{ inputs.app_name }}" "${{ steps.get-commit-hash.outputs.commit_hash }}")
echo "Is image published: $is_image_published"
echo "is_image_published=$is_image_published" >> "$GITHUB_OUTPUT"

build-and-publish:
name: Build and publish
runs-on: ubuntu-latest
needs: get-commit-hash
concurrency: build-and-publish-${{ inputs.app_name }}-${{ needs.get-commit-hash.outputs.commit_hash }}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this concurrency is important to keep. the concurrency statement later on that uses github.ref won't work since different github.refs can refer to the same commit hash (e.g. main, origin/main, HEAD, , ) can all be valid refs that point to the same commit hash, so there'd be a race condition where multiple jobs are trying to build the same commit hash but don't realize it since they are referencing the commit via different refs. that's why we have the separate job beforehand that gets the commit hash.

needs: check-image-already-published
if: ${{ needs.check-image-already-published.outputs.is_image_published != 'true' }}

permissions:
contents: read
id-token: write

concurrency:
group: build-${{ inputs.app_name }}-${{ needs.check-image-already-published.outputs.commit_hash }}
cancel-in-progress: false

steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}

- id: build-release-candidate
uses: ./.github/actions/build-release-candidate
with:
app_name: ${{ inputs.app_name }}

- name: Set up Terraform
uses: ./.github/actions/setup-terraform

Expand All @@ -72,17 +100,5 @@ jobs:
app_name: ${{ inputs.app_name }}
environment: shared

- name: Check if image is already published
id: check-image-published
run: |
is_image_published=$(./bin/is-image-published "${{ inputs.app_name }}" "${{ needs.get-commit-hash.outputs.commit_hash }}")
echo "Is image published: $is_image_published"
echo "is_image_published=$is_image_published" >> "$GITHUB_OUTPUT"

- name: Build release
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reason for making this a separate job?

if: steps.check-image-published.outputs.is_image_published == 'false'
run: make APP_NAME=${{ inputs.app_name }} release-build

- name: Publish release
if: steps.check-image-published.outputs.is_image_published == 'false'
run: make APP_NAME=${{ inputs.app_name }} release-publish
107 changes: 76 additions & 31 deletions .github/workflows/vulnerability-scans.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# GitHub Actions CI workflow that runs vulnerability scans on the application's Docker image
# to ensure images built are secure before they are deployed.
# GitHub Actions CI workflow that runs vulnerability scans on the application's
# Dockerfile or Docker image to ensure images built are secure before they are deployed.

# The docker image is built once and cached, with that image used by the jobs that
# require access to the image.

# NOTE: The workflow isn't able to pass the docker image between jobs, so each builds the image.
# A future PR will pass the image between the scans to reduce overhead and increase speed
name: Vulnerability Scans

on:
Expand Down Expand Up @@ -41,12 +42,56 @@ jobs:
if: always() # Runs even if there is a failure
run: cat hadolint-results.txt >> "$GITHUB_STEP_SUMMARY"

get-commit-hash:
runs-on: ubuntu-latest
outputs:
commit_hash: ${{ steps.get-commit-hash.outputs.image_tag }}

steps:
- uses: actions/checkout@v4

- id: get-commit-hash
run: |
IMAGE_TAG=$(make release-image-tag)
echo "image_tag=$IMAGE_TAG" >> "$GITHUB_OUTPUT"

build:
runs-on: ubuntu-latest
needs: get-commit-hash
outputs:
image: ${{ steps.build-release-candidate.outputs.image_cache_key }}

# to support the build happening only once for a given version, we disable concurrent execution
concurrency:
group: build-${{ inputs.app_name }}-${{ needs.get-commit-hash.outputs.commit_hash }}
cancel-in-progress: false

steps:
- uses: actions/checkout@v4

- id: build-release-candidate
uses: ./.github/actions/build-release-candidate
with:
app_name: ${{ inputs.app_name }}

trivy-scan:
runs-on: ubuntu-latest
needs: build

steps:
- uses: actions/checkout@v4

- name: Restore cached Docker image
uses: actions/cache/restore@v4
with:
path: /tmp/docker-image.tar
key: ${{ needs.build.outputs.image }}
fail-on-cache-miss: true

- name: Load cached Docker image
run: |
docker load < /tmp/docker-image.tar

- uses: ./.github/actions/first-file
id: trivy-ignore
with:
Expand All @@ -59,19 +104,11 @@ jobs:
with:
files: ${{ inputs.app_name }}/trivy-secret.yaml trivy-secret.yaml

- name: Build and tag Docker image for scanning
id: build-image
run: |
make APP_NAME=${{ inputs.app_name }} release-build
IMAGE_NAME=$(make APP_NAME=${{ inputs.app_name }} release-image-name)
IMAGE_TAG=$(make release-image-tag)
echo "image=$IMAGE_NAME:$IMAGE_TAG" >> "$GITHUB_OUTPUT"

- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
scan-type: image
image-ref: ${{ steps.build-image.outputs.image }}
image-ref: ${{ needs.build.outputs.image }}
format: table
exit-code: 1
ignore-unfixed: true
Expand All @@ -88,29 +125,33 @@ jobs:

anchore-scan:
runs-on: ubuntu-latest
needs: build

steps:
- uses: actions/checkout@v4

- name: Restore cached Docker image
uses: actions/cache/restore@v4
with:
path: /tmp/docker-image.tar
key: ${{ needs.build.outputs.image }}
fail-on-cache-miss: true

- name: Load cached Docker image
run: |
docker load < /tmp/docker-image.tar

- uses: ./.github/actions/first-file
id: grype-config
with:
files: |-
${{ inputs.app_name }}/.grype.yml
.grype.yml

- name: Build and tag Docker image for scanning
id: build-image
run: |
make APP_NAME=${{ inputs.app_name }} release-build
IMAGE_NAME=$(make APP_NAME=${{ inputs.app_name }} release-image-name)
IMAGE_TAG=$(make release-image-tag)
echo "image=$IMAGE_NAME:$IMAGE_TAG" >> "$GITHUB_OUTPUT"

- name: Run Anchore vulnerability scan
uses: anchore/scan-action@v3
with:
image: ${{ steps.build-image.outputs.image }}
image: ${{ needs.build.outputs.image }}
output-format: table
env:
GRYPE_CONFIG: ${{ steps.grype-config.outputs.found_file }}
Expand All @@ -121,25 +162,29 @@ jobs:

dockle-scan:
runs-on: ubuntu-latest
needs: build

steps:
- uses: actions/checkout@v4

- name: Restore cached Docker image
uses: actions/cache/restore@v4
with:
path: /tmp/docker-image.tar
key: ${{ needs.build.outputs.image }}
fail-on-cache-miss: true

- name: Load cached Docker image
run: |
docker load < /tmp/docker-image.tar

- uses: ./.github/actions/first-file
id: dockle-config
with:
files: |-
${{ inputs.app_name }}/.dockleconfig
.dockleconfig

- name: Build and tag Docker image for scanning
id: build-image
run: |
make APP_NAME=${{ inputs.app_name }} release-build
IMAGE_NAME=$(make APP_NAME=${{ inputs.app_name }} release-image-name)
IMAGE_TAG=$(make release-image-tag)
echo "image=$IMAGE_NAME:$IMAGE_TAG" >> "$GITHUB_OUTPUT"

# Dockle doesn't allow you to have an ignore file for the DOCKLE_ACCEPT_FILES
# variable, this will save the variable in this file to env for Dockle
- name: Set any acceptable Dockle files
Expand All @@ -151,7 +196,7 @@ jobs:
- name: Run Dockle container linter
uses: erzz/dockle-action@v1.3.1
with:
image: ${{ steps.build-image.outputs.image }}
image: ${{ needs.build.outputs.image }}
exit-code: "1"
failure-threshold: WARN
accept-filenames: ${{ env.DOCKLE_ACCEPT_FILES }}
Expand Down
Loading