main 0608ac3f115b cached
24 files
48.8 KB
14.2k tokens
1 requests
Download .txt
Repository: BretFisher/docker-ci-automation
Branch: main
Commit: 0608ac3f115b
Files: 24
Total size: 48.8 KB

Directory structure:
gitextract_w2qc27yx/

├── .dockerignore
├── .github/
│   ├── dependabot.yml
│   ├── linters/
│   │   ├── .hadolint.yaml
│   │   ├── .markdown-lint.yml
│   │   └── .yaml-lint.yml
│   └── workflows/
│       ├── 01-basic-docker-build.yaml
│       ├── 02-add-buildkit-cache.yaml
│       ├── 03-add-multi-platform.yaml
│       ├── 04-add-metadata.yaml
│       ├── 05-add-comment.yaml
│       ├── 06-add-cve-scanning.yaml
│       ├── 07-add-cve-scanning-adv.yaml
│       ├── 08-add-unit-test.yaml
│       ├── 09-add-integration-test.yaml
│       ├── 10-add-k8s-test.yaml
│       ├── 99-parallelize-jobs.yaml
│       └── call-super-linter.yaml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.test.yml
├── healthchecks/
│   └── postgres-healthcheck
└── manifests/
    └── deployment.yaml

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
.git

================================================
FILE: .github/dependabot.yml
================================================
---
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
  # Maintain dependencies for GitHub Actions
  - package-ecosystem: "github-actions"
    directory: "/"
    cooldown:
      default-days: 7
    schedule:
      interval: "daily"

  # Add this section for each directory with a Dockerfile, K8s manifest, or Helm chart
  # They must use a semver tag, and Dependabot must be able to access the registry
  # You can give it access to private ones:
  # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#configuration-options-for-private-registries
  # follow along on a feature request to support multiple directories in one package-ecosystem
  # https://github.com/dependabot/dependabot-core/issues/2178
  - package-ecosystem: "docker"
    directory: "/"
    cooldown:
      default-days: 7
    schedule:
      interval: "weekly"
    commit-message:
      # Prefix all commit messages with "[docker] "
      prefix: "[docker] "


================================================
FILE: .github/linters/.hadolint.yaml
================================================
---
# README: https://github.com/hadolint/hadolint

# Often it's a good idea to do inline disables rather that repo-wide in this file.
# Example of inline Dockerfile rules:
# hadolint ignore=DL3018
#RUN apk add --no-cache git

# or just ignore rules repo-wide
ignored:
  - DL3003 #ignore that we use cd sometimes
  - DL3006 #image pin versions
  - DL3008 #apt pin versions
  - DL3018 #apk add pin versions
  - DL3022 #bad rule for COPY --from
  - DL3028 #gem install pin versions
  - DL3059 #multiple consecutive runs

# FULL TEMPLATE
# failure-threshold: string               # name of threshold level (error | warning | info | style | ignore | none)
# format: string                          # Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy)
# ignored: [string]                       # list of rules
# label-schema:                           # See Linting Labels below for specific label-schema details
#   author: string                        # Your name
#   contact: string                       # email address
#   created: timestamp                    # rfc3339 datetime
#   version: string                       # semver
#   documentation: string                 # url
#   git-revision: string                  # hash
#   license: string                       # spdx
# no-color: boolean                       # true | false
# no-fail: boolean                        # true | false
# override:
#   error: [string]                       # list of rules
#   warning: [string]                     # list of rules
#   info: [string]                        # list of rules
#   style: [string]                       # list of rules
# strict-labels: boolean                  # true | false
# disable-ignore-pragma: boolean          # true | false
# trustedRegistries: string | [string]    # registry or list of registries


================================================
FILE: .github/linters/.markdown-lint.yml
================================================
---
# MD013/line-length - Line length
MD013:
  # Number of characters, default is 80
  # I'm OK with long lines. All editors now have wordwrap
  line_length: 9999
  # Number of characters for headings
  heading_line_length: 100
  # check code blocks?
  code_blocks: false


================================================
FILE: .github/linters/.yaml-lint.yml
================================================
---
###########################################
# These are the rules used for            #
# linting all the yaml files in the stack #
# NOTE:                                   #
# You can disable line with:              #
# # yamllint disable-line                 #
###########################################
rules:
  braces:
    level: warning
    min-spaces-inside: 0
    max-spaces-inside: 0
    min-spaces-inside-empty: 1
    max-spaces-inside-empty: 5
  brackets:
    level: warning
    min-spaces-inside: 0
    max-spaces-inside: 0
    min-spaces-inside-empty: 1
    max-spaces-inside-empty: 5
  colons:
    level: warning
    max-spaces-before: 0
    max-spaces-after: 1
  commas:
    level: warning
    max-spaces-before: 0
    min-spaces-after: 1
    max-spaces-after: 1
  comments: disable
  comments-indentation: disable
  document-end: disable
  document-start: disable
  empty-lines:
    level: warning
    max: 2
    max-start: 0
    max-end: 0
  hyphens:
    level: warning
    max-spaces-after: 1
  indentation:
    level: warning
    spaces: consistent
    indent-sequences: true
    check-multi-line-strings: false
  key-duplicates: enable
  line-length: disable
  new-line-at-end-of-file: disable
  new-lines:
    type: unix
  trailing-spaces: disable
  truthy: disable

================================================
FILE: .github/workflows/01-basic-docker-build.yaml
================================================
---
name: 01 Basic Docker Build
# simplest workflow possible

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Image
    runs-on: ubuntu-latest
    steps:
            
      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Docker build
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: bretfisher/docker-ci-automation:latest,bretfisher/docker-ci-automation:01


================================================
FILE: .github/workflows/02-add-buildkit-cache.yaml
================================================
---
name: 02 Build with BuildKit Cache

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Image
    runs-on: ubuntu-latest
    steps:

#NEW: (START) ##########################################################
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0
#NEW: (END) ############################################################
            
      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Docker build
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: bretfisher/docker-ci-automation:02
#NEW: (START) ##########################################################
          cache-from: type=gha
          cache-to: type=gha,mode=max
#NEW: (END) ############################################################

================================================
FILE: .github/workflows/03-add-multi-platform.yaml
================================================
---
name: 03 Build with Multi-Platform

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest
    steps:

#NEW: (START) ##########################################################
      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0
#NEW: (END) ############################################################

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0
            
      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Docker build
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: ${{ github.event_name != 'pull_request' }}
          tags: bretfisher/docker-ci-automation:03
          cache-from: type=gha
          cache-to: type=gha,mode=max
#NEW: (START) ##########################################################
          platforms: linux/amd64,linux/arm64,linux/arm/v7
#NEW: (END) ############################################################


================================================
FILE: .github/workflows/04-add-metadata.yaml
================================================
---
name: 04 Build with Metadata

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest
    steps:


      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

#NEW: (START) ##########################################################
      - name: Docker meta
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=04
            type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
            type=ref,event=pr
            type=ref,event=branch
            type=semver,pattern={{version}}
#NEW: (END) ############################################################
      
      - name: Docker build
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
#NEW: (START) ##########################################################
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
#NEW: (END) ############################################################
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/05-add-comment.yaml
================================================
---
name: 05 Build and Comment

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest

#NEW: (START) ##########################################################
    permissions:
      pull-requests: write # needed to create and update comments in PRs
#NEW: (END) ############################################################

    steps:

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Docker meta
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=05
            type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
            type=ref,event=pr
            type=ref,event=branch
            type=semver,pattern={{version}}
      
      - name: Docker build
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: false # false for this demo to prevent overwriting image tags of other examples
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


#NEW: (START) ##########################################################
        # If PR, put image tags in the PR comments
        # from https://github.com/marketplace/actions/create-or-update-comment
      - name: Find comment for image tags
        uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e #v3.1.0
        if: github.event_name == 'pull_request'
        id: fc
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-author: 'github-actions[bot]'
          body-includes: Docker image tag(s) pushed
      
        # If PR, put image tags in the PR comments
      - name: Create or update comment for image tags
        uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 #v4.0.0
        if: github.event_name == 'pull_request'
        with:
          comment-id: ${{ steps.fc.outputs.comment-id }}
          issue-number: ${{ github.event.pull_request.number }}
          body: |
            Docker image tag(s) pushed:
            ```text
            ${{ steps.docker_meta.outputs.tags }}
            ```

            Labels added to images:
            ```text
            ${{ steps.docker_meta.outputs.labels }}
            ```
          edit-mode: replace
#NEW: (END) ############################################################


================================================
FILE: .github/workflows/06-add-cve-scanning.yaml
================================================
---
name: 06 Build and Scan

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest
    
    steps:

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and export to Docker
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: false
          load: true # Export to Docker Engine rather than pushing to a registry
          tags: ${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64

#NEW: (START) ##########################################################
      - name: Run Trivy for all CVEs (non-blocking)
        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master
        with:
          image-ref: ${{ github.run_id }}
          exit-code: 0
          format: table 
#NEW: (END) ############################################################

      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=06
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/07-add-cve-scanning-adv.yaml
================================================
---
name: 07 Build and Scan + Report

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest

#NEW: (START) ##########################################################
    permissions:
      contents: read # for actions/checkout to fetch code
      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
#NEW: (END) ############################################################

    steps:

#NEW: (START) ##########################################################
      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
#NEW: (END) ############################################################

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and export to Docker
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: false
          load: true # Export to Docker Engine rather than pushing to a registry
          tags: ${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64

      - name: Run Trivy for all CVEs (non-blocking)
        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master
        with:
          image-ref: ${{ github.run_id }}
          format: table 
          exit-code: 0

#NEW: (START) ##########################################################
      - name: Run Trivy for HIGH,CRITICAL CVEs and report (blocking)
        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master
        with:
          image-ref: ${{ github.run_id }}
          exit-code: 1
          ignore-unfixed: true
          vuln-type: 'os,library'
          severity: 'HIGH,CRITICAL'
          format: 'sarif'
          output: 'trivy-results.sarif'
      
      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@5c8a8a642e79153f5d047b10ec1cba1d1cc65699 #v3.35.1
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'
#NEW: (END) ############################################################

      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=07
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/08-add-unit-test.yaml
================================================
---
name: 08 Build and Unit Test

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest
    steps:


      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

#NEW: (START) ##########################################################
      - name: Build and export to Docker
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: false
          load: true # Export to Docker Engine rather than pushing to a registry
          tags: ${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64

        # for simple tests (npm test, etc.) just run a local image in docker
      - name: Unit Testing in Docker
        run: |
          docker run --rm ${{ github.run_id }} echo "run test commands here"
#NEW: (END) ############################################################

      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=08
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/09-add-integration-test.yaml
================================================
---
name: 09 Build and Integration Test

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest

    steps:

      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and export to Docker
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: false
          load: true # Export to Docker Engine rather than pushing to a registry
          tags: ${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64

#NEW: (START) ############################################################  
        # for more advanced tests, use docker compose with `depends_on`
          # NOTE: GHA and other CIs can also run dependency containers on their own
          # GHA `services:` can do this if you're trying to avoid docker compose
      - name: Test healthcheck in Docker Compose
        run: |
          export TESTING_IMAGE="${{ github.run_id }}"
          docker compose -f docker-compose.test.yml up --exit-code-from sut
#NEW: (END) ############################################################  


      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=09
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/10-add-k8s-test.yaml
================================================
---
name: 10 Build and Smoke Test

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  build-image:
    name: Build Images
    runs-on: ubuntu-latest

    permissions:
      packages: write # needed to push docker image to ghcr.io

    steps:

      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

#NEW: (START) ############################################################
      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Build and Push to GHCR
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64

      - uses: AbsaOSS/k3d-action@4e8b3239042be1dc0aed6c5eb80c13b18200fc79 #v2.4.0
        with:
          cluster-name: "test-cluster-1"
          args: >-
            --agents 1
            --no-lb
            --k3s-arg "--no-deploy=traefik,servicelb,metrics-server@server:*"
      
      - name: Smoke test deployment in k3d Kubernetes
        run: |
          kubectl create secret docker-registry regcred \
            --docker-server=https://ghcr.io \
            --docker-username=${{ github.actor }} \
            --docker-password=${{ secrets.GITHUB_TOKEN }}
          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:"$GITHUB_RUN_ID"
          envsubst < manifests/deployment.yaml  | kubectl apply -f -
          kubectl rollout status deployment myapp
          kubectl exec deploy/myapp -- curl --fail localhost
#NEW: (END) ############################################################  

      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation,ghcr.io/bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=10
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64


================================================
FILE: .github/workflows/99-parallelize-jobs.yaml
================================================
---
name: 99 Parallelize Jobs

on:
  push:
    branches:
      - main
  pull_request:

jobs:
# FIRST JOB #######################################################################   
  build-test-image:
    name: Build Image for Testing
    runs-on: ubuntu-latest

    permissions:
      packages: write # needed to push docker image to ghcr.io

    steps:

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Build and Push to GHCR
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}
          target: test
          cache-from: type=gha
          cache-to: type=gha,mode=max
          platforms: linux/amd64
    
 # NEXT JOB #######################################################################   
  test-unit:
    name: Unit tests in Docker
    needs: [build-test-image]
    runs-on: ubuntu-latest

    permissions:
      packages: read
      
    steps:
      
      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      
      - name: Unit Testing in Docker
        run: docker run --rm ghcr.io/bretfisher/docker-ci-automation:"$GITHUB_RUN_ID" echo "run test commands here"

# NEXT JOB #######################################################################   
  test-integration:
    name: Integration tests in Compose
    needs: [build-test-image]
    runs-on: ubuntu-latest

    permissions:
      packages: read

    steps:

      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Test healthcheck in Docker Compose
        run: |
          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:"$GITHUB_RUN_ID"
          echo Testing image: "$TESTING_IMAGE"
          docker compose -f docker-compose.test.yml up --exit-code-from sut

# NEXT JOB #######################################################################   
  test-k3d:
    name: Test Deployment in Kubernetes
    needs: [build-test-image]
    runs-on: ubuntu-latest

    permissions:
      packages: read

    steps:

      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      
      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: AbsaOSS/k3d-action@4e8b3239042be1dc0aed6c5eb80c13b18200fc79 #v2.4.0
        with:
          cluster-name: "test-cluster-1"
          args: >-
            --agents 1
            --no-lb
            --k3s-arg "--no-deploy=traefik,servicelb,metrics-server@server:*"
      
      - name: Smoke test deployment in k3d Kubernetes
        run: |
          kubectl create secret docker-registry regcred \
            --docker-server=https://ghcr.io \
            --docker-username=${{ github.actor }} \
            --docker-password=${{ secrets.GITHUB_TOKEN }}
          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:"$GITHUB_RUN_ID"
          envsubst < manifests/deployment.yaml  | kubectl apply -f -
          kubectl rollout status deployment myapp
          kubectl exec deploy/myapp -- curl --fail localhost

# NEXT JOB #######################################################################   
  scan-image:
    name: Scan Image with Trivy
    needs: [build-test-image]
    runs-on: ubuntu-latest

    permissions:
      contents: read # for actions/checkout to fetch code
      packages: read # needed to pull docker image to ghcr.io
      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results

    steps:

      - name: Checkout git repo
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
      
      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
          
      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Pull image to scan
        run: docker pull ghcr.io/bretfisher/docker-ci-automation:"$GITHUB_RUN_ID"
        
      - name: Run Trivy for all CVEs (non-blocking)
        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master
        with:
          image-ref: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}
          format: table
          exit-code: 0

      # NOTE: disabled to avoid running twice and overwriting 07-add-cve-scanning-adv.yaml
      # - name: Run Trivy for HIGH,CRITICAL CVEs and report (blocking)
      #   uses: aquasecurity/trivy-action@master
      #   with:
      #     image-ref: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}
      #     exit-code: 1
      #     ignore-unfixed: true
      #     vuln-type: 'os,library'
      #     severity: 'HIGH,CRITICAL'
      #     format: 'sarif'
      #     output: 'trivy-results.sarif'
      
      # - name: Upload Trivy scan results to GitHub Security tab
      #   uses: github/codeql-action/upload-sarif@v1
      #   if: always()
      #   with:
      #     sarif_file: 'trivy-results.sarif'

# NEXT JOB #######################################################################   
  build-final-image:
    name: Build Final Image
    needs: [test-unit, test-integration, test-k3d, scan-image]
    runs-on: ubuntu-latest

    permissions:
      packages: write # needed to push docker image to ghcr.io
      pull-requests: write # needed to create and update comments in PRs

    steps:

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0

      - name: Login to Docker Hub
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Login to ghcr.io registry
        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Docker Metadata for Final Image Build
        id: docker_meta
        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0
        with:
          images: bretfisher/docker-ci-automation,ghcr.io/bretfisher/docker-ci-automation
          flavor: |
            latest=false
          tags: |
            type=raw,value=99
          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags
          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
          # type=ref,event=pr
          # type=ref,event=branch
          # type=semver,pattern={{version}}
      
      - name: Docker Build and Push to GHCR and Docker Hub
        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0
        with:
          push: true
          tags: ${{ steps.docker_meta.outputs.tags }}
          labels: ${{ steps.docker_meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          # comma seperated list of what OS and architechtures to build for (in parallel)
          # default is linux/amd64 (the OS of the runner) but you can add more
          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.
          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3
          platforms: linux/amd64,linux/arm64

        # If PR, put image tags in the PR comments
        # from https://github.com/marketplace/actions/create-or-update-comment
        # These are commented out to avoid conflicting with 05-add-comments.yaml example
      # - name: Find comment for image tags
      #   uses: peter-evans/find-comment@v1
      #   if: github.event_name == 'pull_request'
      #   id: fc
      #   with:
      #     issue-number: ${{ github.event.pull_request.number }}
      #     comment-author: 'github-actions[bot]'
      #     body-includes: Docker image tag(s) pushed
      
      #   # If PR, put image tags in the PR comments
      # - name: Create or update comment for image tags
      #   uses: peter-evans/create-or-update-comment@v1
      #   if: github.event_name == 'pull_request'
      #   with:
      #     comment-id: ${{ steps.fc.outputs.comment-id }}
      #     issue-number: ${{ github.event.pull_request.number }}
      #     body: |
      #       Docker image tag(s) pushed:
      #       ```text
      #       ${{ steps.docker_meta.outputs.tags }}
      #       ```

      #       Labels added to images:
      #       ```text
      #       ${{ steps.docker_meta.outputs.labels }}
      #       ```
      #     edit-mode: replace


================================================
FILE: .github/workflows/call-super-linter.yaml
================================================
---
# template source: https://github.com/bretfisher/super-linter-workflow/blob/main/templates/call-super-linter.yaml
name: Lint Code Base

on:
  # run anytime a PR is merged to main or a direct push to main
  push:
    branches: [main]

  # run on any push to a PR branch
  pull_request:

# cancel any previously-started, yet still active runs of this workflow on the same branch
concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true

# reset permissions to none at the workflow level
# we'll set them at the job level below
permissions: {}

jobs:
  call-super-linter:
    name: Call Super-Linter

    permissions:
      contents: read # clone the repository to lint
      pull-requests: write # create a summary comment in PR
      statuses: write # read/write to repository custom statuses

    ### use Reusable Workflows to call my workflow remotely
    ### https://docs.github.com/en/actions/learn-github-actions/reusing-workflows
    ### you can also call workflows from inside the same repository via file path

    # FIXME: customize uri to point to your own reusable linter repository
    # NOTE: zizmor scanner rule ignore added because we control sha pins via reusable workflow, not calling workflow
    uses: bretfisher/super-linter-workflow/.github/workflows/reusable-super-linter.yaml@main # zizmor: ignore[unpinned-uses]


    ### Optional settings examples

    # with:
    ### 1. Remember .github/super-linter.env is injected for setting linter on/off

    ### 2. For a DevOps-focused repository. Prevents some code-language linters from running
    ### defaults to false
    # devops-only: false

    ### 3. A regex to exclude files from linting
    ### defaults to empty
    # filter-regex-exclude: html/.*
    #
    ### 4. Additional environment variables to pass to super-linter (one per line)
    # extra-envs: |
    #   VALIDATE_DOCKERFILE=false
    #   VALIDATE_JSCPD=false
    #   VALIDATE_TRIVY=false


================================================
FILE: .gitignore
================================================
TODO-*.yaml

================================================
FILE: Dockerfile
================================================
# sample dockerfile for testing docker builds
FROM nginx:1.20-alpine as base

RUN apk add --no-cache curl

WORKDIR /test

COPY . .

#########################
FROM base as test

#layer test tools and assets on top as optional test stage
RUN apk add --no-cache apache2-utils


#########################
FROM base as final

# this layer gets built by default unless you set target to test


================================================
FILE: LICENSE
================================================
This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <https://unlicense.org>


================================================
FILE: README.md
================================================
# Automation with Docker for CI Workflows

[![Lint Code Base](https://github.com/bretfisher/docker-ci-automation/actions/workflows/call-super-linter.yaml/badge.svg)](https://github.com/bretfisher/docker-ci-automation/actions/workflows/call-super-linter.yaml)

> For Docker Community All Hands 2022

[![All-Hands Automation with Docker](https://user-images.githubusercontent.com/792287/160971371-0ae75c14-1ea4-4a11-82dc-f35f96184fa3.gif)](https://www.youtube.com/watch?v=aZzV6X7XhyI)

Watch the walkthrough of this repo: [https://www.youtube.com/watch?v=aZzV6X7XhyI](https://www.youtube.com/watch?v=aZzV6X7XhyI)

See this repositories' [`.github/workflows`](.github/workflows) directory for the below example workflows, ordered by number, simple to complex.

These examples are focused on five of Docker's [official GitHub Actions](https://github.com/marketplace?type=actions&query=publisher%3Adocker+).

These examples are based on three workflow diagrams on progressively more complex automation pipelines:

1. [Basic code PR automation workflow](diagrams/basic-code-pr.png)
2. [Intermediate code PR automation workflow](diagrams/intermediate-code-pr.png)
3. [Advanced code PR automation workflow](diagrams/advanced-code-pr.png)

I also have a [LIVE course on learning GitHub Actions for DevOps automation and Argo CD](https://bret.courses/autodeploy) for GitOps-style deployments.

## Example Workflows

1. Basic Docker build
2. Adding BuildKit cache
3. Adding multi-platform builds
4. Adding metadata to images
5. Adding comments with image tags to PRs
6. Adding CVE scanning
7. Adding CVE security reporting
8. Adding unit testing
9. Adding integration testing
10. Adding Kubernetes smoke tests
11. Adding job parallelizing for mucho speed

## GitHub Actions shown in these examples

- [Docker Login](https://github.com/marketplace/actions/docker-login)
- [Docker Setup Buildx](https://github.com/marketplace/actions/docker-setup-buildx)
- [Docker Setup QEMU](https://github.com/marketplace/actions/docker-setup-qemu)
- [Docker Metadata](https://github.com/marketplace/actions/docker-metadata-action)
- [Docker Build and Push](https://github.com/marketplace/actions/build-and-push-docker-images)
- [Aqua Security Trivy CVE Scan](https://github.com/marketplace/actions/aqua-security-trivy)
- [Super-Linter](https://github.com/marketplace/actions/super-linter)
- [Setup k3d](https://github.com/marketplace/actions/absaoss-k3d-action)
- [Find Comment](https://github.com/marketplace/actions/find-comment)
- [Create or Update Comment](https://github.com/marketplace/actions/create-or-update-comment)

## This repository is part of my example DevOps repos on GitHub Actions

- [bretfisher/github-actions-templates](https://github.com/BretFisher/github-actions-templates) - Main reusable templates repository
- [bretfisher/super-linter-workflow](https://github.com/BretFisher/super-linter-workflow) - Reusable linter workflow
- [bretfisher/docker-build-workflow](https://github.com/BretFisher/docker-build-workflow)- Reusable docker build workflow
- (you are here) [bretfisher/docker-ci-automation](https://github.com/BretFisher/docker-ci-automation) - Step by step video and example of a Docker CI workflow
- [My full list of container examples and tools](https://github.com/bretfisher)

## More reading

[Docker Build/Push Action advanced examples](https://github.com/docker/build-push-action/tree/master/docs/advanced)
[My full list of container examples and tools](https://github.com/bretfisher)

## 🎉🎉🎉 Join my container DevOps community 🎉🎉🎉

- [My "Vital DevOps" Discord server](https://devops.fan)
- [My weekly YouTube Live show](https://bret.live)
- [My courses and coupons](https://www.bretfisher.com/courses)


================================================
FILE: docker-compose.test.yml
================================================
services:
  allhands22:
    image: "${TESTING_IMAGE}"
  
  postgres:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    volumes:
      - ./healthchecks:/healthchecks
    healthcheck:
      test: /healthchecks/postgres-healthcheck
      interval: "5s"
  sut:
    image: "${TESTING_IMAGE}"
    depends_on:
      allhands22:
        condition: service_started
      postgres:
        condition: service_healthy
    # run all your tests here against the allhands22 service
    command: curl --fail http://allhands22:80 || exit 1

================================================
FILE: healthchecks/postgres-healthcheck
================================================
#!/bin/bash
set -eo pipefail

host="$(hostname -i || echo '127.0.0.1')"
user="${POSTGRES_USER:-postgres}"
db="${POSTGRES_DB:-$POSTGRES_USER}"
export PGPASSWORD="${POSTGRES_PASSWORD:-}"

args=(
	# force postgres to not use the local unix socket (test "external" connectibility)
	--host "$host"
	--username "$user"
	--dbname "$db"
	--quiet --no-align --tuples-only
)

if select="$(echo 'SELECT 1' | psql "${args[@]}")" && [ "$select" = '1' ]; then
	exit 0
fi

exit 1

================================================
FILE: manifests/deployment.yaml
================================================
# kubernetes deployment
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      imagePullSecrets:
        - name: regcred
      containers:
        - name: myapp
          image: "${TESTING_IMAGE}"
          imagePullPolicy: IfNotPresent
Download .txt
gitextract_w2qc27yx/

├── .dockerignore
├── .github/
│   ├── dependabot.yml
│   ├── linters/
│   │   ├── .hadolint.yaml
│   │   ├── .markdown-lint.yml
│   │   └── .yaml-lint.yml
│   └── workflows/
│       ├── 01-basic-docker-build.yaml
│       ├── 02-add-buildkit-cache.yaml
│       ├── 03-add-multi-platform.yaml
│       ├── 04-add-metadata.yaml
│       ├── 05-add-comment.yaml
│       ├── 06-add-cve-scanning.yaml
│       ├── 07-add-cve-scanning-adv.yaml
│       ├── 08-add-unit-test.yaml
│       ├── 09-add-integration-test.yaml
│       ├── 10-add-k8s-test.yaml
│       ├── 99-parallelize-jobs.yaml
│       └── call-super-linter.yaml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.test.yml
├── healthchecks/
│   └── postgres-healthcheck
└── manifests/
    └── deployment.yaml
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (53K chars).
[
  {
    "path": ".dockerignore",
    "chars": 4,
    "preview": ".git"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 1299,
    "preview": "---\n# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and wh"
  },
  {
    "path": ".github/linters/.hadolint.yaml",
    "chars": 1864,
    "preview": "---\n# README: https://github.com/hadolint/hadolint\n\n# Often it's a good idea to do inline disables rather that repo-wide"
  },
  {
    "path": ".github/linters/.markdown-lint.yml",
    "chars": 272,
    "preview": "---\n# MD013/line-length - Line length\nMD013:\n  # Number of characters, default is 80\n  # I'm OK with long lines. All edi"
  },
  {
    "path": ".github/linters/.yaml-lint.yml",
    "chars": 1291,
    "preview": "---\n###########################################\n# These are the rules used for            #\n# linting all the yaml files"
  },
  {
    "path": ".github/workflows/01-basic-docker-build.yaml",
    "chars": 733,
    "preview": "---\nname: 01 Basic Docker Build\n# simplest workflow possible\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njo"
  },
  {
    "path": ".github/workflows/02-add-buildkit-cache.yaml",
    "chars": 1158,
    "preview": "---\nname: 02 Build with BuildKit Cache\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n   "
  },
  {
    "path": ".github/workflows/03-add-multi-platform.yaml",
    "chars": 1333,
    "preview": "---\nname: 03 Build with Multi-Platform\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n   "
  },
  {
    "path": ".github/workflows/04-add-metadata.yaml",
    "chars": 2177,
    "preview": "---\nname: 04 Build with Metadata\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name:"
  },
  {
    "path": ".github/workflows/05-add-comment.yaml",
    "chars": 3537,
    "preview": "---\nname: 05 Build and Comment\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: B"
  },
  {
    "path": ".github/workflows/06-add-cve-scanning.yaml",
    "chars": 2828,
    "preview": "---\nname: 06 Build and Scan\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Buil"
  },
  {
    "path": ".github/workflows/07-add-cve-scanning-adv.yaml",
    "chars": 4059,
    "preview": "---\nname: 07 Build and Scan + Report\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    n"
  },
  {
    "path": ".github/workflows/08-add-unit-test.yaml",
    "chars": 2790,
    "preview": "---\nname: 08 Build and Unit Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name:"
  },
  {
    "path": ".github/workflows/09-add-integration-test.yaml",
    "chars": 3142,
    "preview": "---\nname: 09 Build and Integration Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n  "
  },
  {
    "path": ".github/workflows/10-add-k8s-test.yaml",
    "chars": 3872,
    "preview": "---\nname: 10 Build and Smoke Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name"
  },
  {
    "path": ".github/workflows/99-parallelize-jobs.yaml",
    "chars": 10821,
    "preview": "---\nname: 99 Parallelize Jobs\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n# FIRST JOB ###############"
  },
  {
    "path": ".github/workflows/call-super-linter.yaml",
    "chars": 1963,
    "preview": "---\n# template source: https://github.com/bretfisher/super-linter-workflow/blob/main/templates/call-super-linter.yaml\nna"
  },
  {
    "path": ".gitignore",
    "chars": 11,
    "preview": "TODO-*.yaml"
  },
  {
    "path": "Dockerfile",
    "chars": 386,
    "preview": "# sample dockerfile for testing docker builds\nFROM nginx:1.20-alpine as base\n\nRUN apk add --no-cache curl\n\nWORKDIR /test"
  },
  {
    "path": "LICENSE",
    "chars": 1211,
    "preview": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, c"
  },
  {
    "path": "README.md",
    "chars": 3717,
    "preview": "# Automation with Docker for CI Workflows\n\n[![Lint Code Base](https://github.com/bretfisher/docker-ci-automation/actions"
  },
  {
    "path": "docker-compose.test.yml",
    "chars": 578,
    "preview": "services:\n  allhands22:\n    image: \"${TESTING_IMAGE}\"\n  \n  postgres:\n    image: postgres\n    environment:\n      POSTGRES"
  },
  {
    "path": "healthchecks/postgres-healthcheck",
    "chars": 464,
    "preview": "#!/bin/bash\nset -eo pipefail\n\nhost=\"$(hostname -i || echo '127.0.0.1')\"\nuser=\"${POSTGRES_USER:-postgres}\"\ndb=\"${POSTGRES"
  },
  {
    "path": "manifests/deployment.yaml",
    "chars": 413,
    "preview": "# kubernetes deployment\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: myapp\n  labels:\n    app: myapp\nspec:\n"
  }
]

About this extraction

This page contains the full source code of the BretFisher/docker-ci-automation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (48.8 KB), approximately 14.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!