diff --git a/.github/actions/lint/action.yml b/.github/actions/lint/action.yml index dc326cc..aeff22a 100644 --- a/.github/actions/lint/action.yml +++ b/.github/actions/lint/action.yml @@ -15,6 +15,7 @@ runs: with: dockerfile: ${{ inputs.dockerfile-location }}/Dockerfile ignore: SC1091,${{ inputs.ignore-linting-rules }} + - name: ShellCheck run: | cd ${{ inputs.dockerfile-location }} diff --git a/.github/actions/push/action.yml b/.github/actions/push/action.yml index 0d8dfca..382485b 100644 --- a/.github/actions/push/action.yml +++ b/.github/actions/push/action.yml @@ -36,10 +36,13 @@ runs: registry: ghcr.io username: ${{ github.actor }} password: ${{ inputs.github-token }} + - name: Set up QEMU uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Build and push image uses: docker/build-push-action@v6 with: @@ -56,9 +59,11 @@ runs: push: true tags: ${{ inputs.image-id }}:${{ inputs.image-tag }} provenance: false + - name: List manifest run: docker buildx imagetools inspect ${{ inputs.image-id }}:${{ inputs.image-tag }} shell: bash + - name: Build and push versioned and latest image tags if: startsWith(github.ref, 'refs/tags/') uses: docker/build-push-action@v6 diff --git a/.github/actions/scan/action.yml b/.github/actions/scan/action.yml index 05e2097..5676db8 100644 --- a/.github/actions/scan/action.yml +++ b/.github/actions/scan/action.yml @@ -18,6 +18,7 @@ runs: format: "sarif" output: "trivy-results.sarif" ignore-unfixed: true + - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 with: diff --git a/.github/actions/build/action.yml b/.github/actions/test-build/action.yml similarity index 98% rename from .github/actions/build/action.yml rename to .github/actions/test-build/action.yml index cd35b3b..1296e31 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/test-build/action.yml @@ -1,4 +1,4 @@ -name: Build test Docker image +name: Test Docker image build inputs: image-name: @@ -15,17 +15,6 @@ inputs: type: string default: app -outputs: - image-id: - value: ${{ steps.generate-tags.outputs.image-id }} - tag: - description: "The generated tag" - value: ${{ steps.generate-tags.outputs.tag }} - major-version: - value: ${{ steps.generate-tags.outputs.major-version }} - minor-version: - value: ${{ steps.generate-tags.outputs.minor-version }} - runs: using: "composite" steps: @@ -48,6 +37,7 @@ runs: echo "major-version=$MAJOR_VERSION" >> "$GITHUB_OUTPUT" echo "minor-version=$MINOR_VERSION" >> "$GITHUB_OUTPUT" shell: bash + - name: Build images uses: docker/build-push-action@v6 with: @@ -64,3 +54,14 @@ runs: load: true tags: ${{ steps.generate-tags.outputs.image-id }}:${{ steps.generate-tags.outputs.tag }} provenance: false + +outputs: + image-id: + value: ${{ steps.generate-tags.outputs.image-id }} + tag: + description: "The generated tag" + value: ${{ steps.generate-tags.outputs.tag }} + major-version: + value: ${{ steps.generate-tags.outputs.major-version }} + minor-version: + value: ${{ steps.generate-tags.outputs.minor-version }} diff --git a/.github/actions/test/action.yml b/.github/actions/test-container/action.yml similarity index 98% rename from .github/actions/test/action.yml rename to .github/actions/test-container/action.yml index 94480eb..46b1413 100644 --- a/.github/actions/test/action.yml +++ b/.github/actions/test-container/action.yml @@ -1,4 +1,4 @@ -name: Test the Docker image user +name: Test Docker image inputs: application-repository: @@ -25,6 +25,7 @@ runs: with: repository: ${{ inputs.application-repository }} path: ${{ inputs.application-repository }} + - name: Start application run: | cd ${{ inputs.application-repository }} @@ -35,9 +36,11 @@ runs: echo "PORT=$PORT" >> "$GITHUB_ENV" docker compose up ${{ inputs.service }} -d shell: bash + - name: Check healthcheck endpoint run: for c in {1..30}; do sleep 1 && curl -s -w '%{http_code}' -o /dev/null http://localhost:${{ env.PORT }}/healthcheck/live/ | grep -o "200" && break; done shell: bash + - name: Check user run: | cd ${{ inputs.application-repository }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67d94ea..9d3393e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,6 +28,7 @@ jobs: python: name: Python runs-on: ubuntu-latest + timeout-minutes: 15 env: IMAGE_NAME: tna-python DOCKERFILE_LOCATION: docker/tna-python @@ -36,34 +37,42 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/lint + + - name: Lint Dockerfile + uses: ./.github/actions/lint with: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} ignore-linting-rules: DL3002,DL3006 - - id: build - uses: ./.github/actions/build + + - name: Test Docker image build + id: build + uses: ./.github/actions/test-build with: image-name: ${{ env.IMAGE_NAME }} base-image: ${{ env.BASE_IMAGE }} dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} + - name: Test Flask - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/flask-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: app + - name: Test FastAPI - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/fastapi-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: app - - uses: ./.github/actions/push + + - name: Build and push Docker images + uses: ./.github/actions/push with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -73,7 +82,9 @@ jobs: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} github-token: ${{ secrets.GITHUB_TOKEN }} - - uses: ./.github/actions/scan + + - name: Scan Docker image + uses: ./.github/actions/scan with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -81,6 +92,7 @@ jobs: python-root: name: Python (root) runs-on: ubuntu-latest + timeout-minutes: 15 env: IMAGE_NAME: tna-python-root DOCKERFILE_LOCATION: docker/tna-python @@ -89,34 +101,42 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/lint + + - name: Lint Dockerfile + uses: ./.github/actions/lint with: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} ignore-linting-rules: DL3002,DL3006 - - id: build - uses: ./.github/actions/build + + - name: Test Docker image build + id: build + uses: ./.github/actions/test-build with: image-name: ${{ env.IMAGE_NAME }} base-image: ${{ env.BASE_IMAGE }} dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} + - name: Test Flask - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/flask-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: root + - name: Test FastAPI - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/fastapi-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: root - - uses: ./.github/actions/push + + - name: Build and push Docker images + uses: ./.github/actions/push with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -126,7 +146,9 @@ jobs: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} github-token: ${{ secrets.GITHUB_TOKEN }} - - uses: ./.github/actions/scan + + - name: Scan Docker image + uses: ./.github/actions/scan with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -135,6 +157,7 @@ jobs: name: Python Django needs: python runs-on: ubuntu-latest + timeout-minutes: 5 env: IMAGE_NAME: tna-python-django DOCKERFILE_LOCATION: docker/tna-python-django @@ -143,25 +166,32 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/lint + + - name: Lint Dockerfile + uses: ./.github/actions/lint with: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} - - id: build - uses: ./.github/actions/build + + - name: Test Docker image build + id: build + uses: ./.github/actions/test-build with: image-name: ${{ env.IMAGE_NAME }} base-image: ${{ env.BASE_IMAGE }} dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} + - name: Test Django - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/django-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: app - - uses: ./.github/actions/push + + - name: Build and push Docker images + uses: ./.github/actions/push with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -171,7 +201,9 @@ jobs: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} github-token: ${{ secrets.GITHUB_TOKEN }} - - uses: ./.github/actions/scan + + - name: Scan Docker image + uses: ./.github/actions/scan with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -180,6 +212,7 @@ jobs: name: Python Django (root) needs: python-root runs-on: ubuntu-latest + timeout-minutes: 5 env: IMAGE_NAME: tna-python-django-root DOCKERFILE_LOCATION: docker/tna-python-django @@ -188,26 +221,33 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/lint + + - name: Lint Dockerfile + uses: ./.github/actions/lint with: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} ignore-linting-rules: DL3002 - - id: build - uses: ./.github/actions/build + + - name: Test Docker image build + id: build + uses: ./.github/actions/test-build with: image-name: ${{ env.IMAGE_NAME }} base-image: ${{ env.BASE_IMAGE }} dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} + - name: Test Django - uses: ./.github/actions/test + uses: ./.github/actions/test-container with: application-repository: nationalarchives/django-application-template service: app image: ${{ env.IMAGE_NAME }} image-tag: ${{ steps.build.outputs.tag }} expected-user: root - - uses: ./.github/actions/push + + - name: Build and push Docker images + uses: ./.github/actions/push with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -217,7 +257,9 @@ jobs: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} github-token: ${{ secrets.GITHUB_TOKEN }} - - uses: ./.github/actions/scan + + - name: Scan Docker image + uses: ./.github/actions/scan with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -226,6 +268,7 @@ jobs: name: Python Dev needs: python-root runs-on: ubuntu-latest + timeout-minutes: 5 env: IMAGE_NAME: tna-python-dev DOCKERFILE_LOCATION: docker/tna-python-dev @@ -234,18 +277,24 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: ./.github/actions/lint + + - name: Lint Dockerfile + uses: ./.github/actions/lint with: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} ignore-linting-rules: DL3002,DL3006 - - id: build - uses: ./.github/actions/build + + - name: Test Docker image build + id: build + uses: ./.github/actions/test-build with: image-name: ${{ env.IMAGE_NAME }} base-image: ${{ env.BASE_IMAGE }} dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} - - uses: ./.github/actions/push + + - name: Build and push Docker images + uses: ./.github/actions/push with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} @@ -255,7 +304,9 @@ jobs: dockerfile-location: ${{ env.DOCKERFILE_LOCATION }} user-image: ${{ env.USER_IMAGE }} github-token: ${{ secrets.GITHUB_TOKEN }} - - uses: ./.github/actions/scan + + - name: Scan Docker image + uses: ./.github/actions/scan with: image-id: ${{ steps.build.outputs.image-id }} image-tag: ${{ steps.build.outputs.tag }} diff --git a/.github/workflows/branch-cleanup.yml b/.github/workflows/cleanup-branches.yml similarity index 99% rename from .github/workflows/branch-cleanup.yml rename to .github/workflows/cleanup-branches.yml index 2aadd2f..b8e98ca 100644 --- a/.github/workflows/branch-cleanup.yml +++ b/.github/workflows/cleanup-branches.yml @@ -27,8 +27,10 @@ jobs: # Strip git ref prefix from version VERSION=$(echo "${{ github.event.ref }}" | sed -e 's,.*/\(.*\),\1,') echo "TAG=$VERSION" >> "$GITHUB_ENV" + - name: Output image tag run: echo "Clean up Docker image ${{ env.IMAGE_ID }}:${{ env.TAG }}" + - name: Delete image uses: bots-house/ghcr-delete-image-action@v1.1.0 with: