[
  {
    "path": ".dockerignore",
    "content": ".git"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "---\n# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  # Maintain dependencies for GitHub Actions\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    cooldown:\n      default-days: 7\n    schedule:\n      interval: \"daily\"\n\n  # Add this section for each directory with a Dockerfile, K8s manifest, or Helm chart\n  # They must use a semver tag, and Dependabot must be able to access the registry\n  # You can give it access to private ones:\n  # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#configuration-options-for-private-registries\n  # follow along on a feature request to support multiple directories in one package-ecosystem\n  # https://github.com/dependabot/dependabot-core/issues/2178\n  - package-ecosystem: \"docker\"\n    directory: \"/\"\n    cooldown:\n      default-days: 7\n    schedule:\n      interval: \"weekly\"\n    commit-message:\n      # Prefix all commit messages with \"[docker] \"\n      prefix: \"[docker] \"\n"
  },
  {
    "path": ".github/linters/.hadolint.yaml",
    "content": "---\n# README: https://github.com/hadolint/hadolint\n\n# Often it's a good idea to do inline disables rather that repo-wide in this file.\n# Example of inline Dockerfile rules:\n# hadolint ignore=DL3018\n#RUN apk add --no-cache git\n\n# or just ignore rules repo-wide\nignored:\n  - DL3003 #ignore that we use cd sometimes\n  - DL3006 #image pin versions\n  - DL3008 #apt pin versions\n  - DL3018 #apk add pin versions\n  - DL3022 #bad rule for COPY --from\n  - DL3028 #gem install pin versions\n  - DL3059 #multiple consecutive runs\n\n# FULL TEMPLATE\n# failure-threshold: string               # name of threshold level (error | warning | info | style | ignore | none)\n# format: string                          # Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy)\n# ignored: [string]                       # list of rules\n# label-schema:                           # See Linting Labels below for specific label-schema details\n#   author: string                        # Your name\n#   contact: string                       # email address\n#   created: timestamp                    # rfc3339 datetime\n#   version: string                       # semver\n#   documentation: string                 # url\n#   git-revision: string                  # hash\n#   license: string                       # spdx\n# no-color: boolean                       # true | false\n# no-fail: boolean                        # true | false\n# override:\n#   error: [string]                       # list of rules\n#   warning: [string]                     # list of rules\n#   info: [string]                        # list of rules\n#   style: [string]                       # list of rules\n# strict-labels: boolean                  # true | false\n# disable-ignore-pragma: boolean          # true | false\n# trustedRegistries: string | [string]    # registry or list of registries\n"
  },
  {
    "path": ".github/linters/.markdown-lint.yml",
    "content": "---\n# MD013/line-length - Line length\nMD013:\n  # Number of characters, default is 80\n  # I'm OK with long lines. All editors now have wordwrap\n  line_length: 9999\n  # Number of characters for headings\n  heading_line_length: 100\n  # check code blocks?\n  code_blocks: false\n"
  },
  {
    "path": ".github/linters/.yaml-lint.yml",
    "content": "---\n###########################################\n# These are the rules used for            #\n# linting all the yaml files in the stack #\n# NOTE:                                   #\n# You can disable line with:              #\n# # yamllint disable-line                 #\n###########################################\nrules:\n  braces:\n    level: warning\n    min-spaces-inside: 0\n    max-spaces-inside: 0\n    min-spaces-inside-empty: 1\n    max-spaces-inside-empty: 5\n  brackets:\n    level: warning\n    min-spaces-inside: 0\n    max-spaces-inside: 0\n    min-spaces-inside-empty: 1\n    max-spaces-inside-empty: 5\n  colons:\n    level: warning\n    max-spaces-before: 0\n    max-spaces-after: 1\n  commas:\n    level: warning\n    max-spaces-before: 0\n    min-spaces-after: 1\n    max-spaces-after: 1\n  comments: disable\n  comments-indentation: disable\n  document-end: disable\n  document-start: disable\n  empty-lines:\n    level: warning\n    max: 2\n    max-start: 0\n    max-end: 0\n  hyphens:\n    level: warning\n    max-spaces-after: 1\n  indentation:\n    level: warning\n    spaces: consistent\n    indent-sequences: true\n    check-multi-line-strings: false\n  key-duplicates: enable\n  line-length: disable\n  new-line-at-end-of-file: disable\n  new-lines:\n    type: unix\n  trailing-spaces: disable\n  truthy: disable"
  },
  {
    "path": ".github/workflows/01-basic-docker-build.yaml",
    "content": "---\nname: 01 Basic Docker Build\n# simplest workflow possible\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Image\n    runs-on: ubuntu-latest\n    steps:\n            \n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      \n      - name: Docker build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: ${{ github.event_name != 'pull_request' }}\n          tags: bretfisher/docker-ci-automation:latest,bretfisher/docker-ci-automation:01\n"
  },
  {
    "path": ".github/workflows/02-add-buildkit-cache.yaml",
    "content": "---\nname: 02 Build with BuildKit Cache\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Image\n    runs-on: ubuntu-latest\n    steps:\n\n#NEW: (START) ##########################################################\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n#NEW: (END) ############################################################\n            \n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      \n      - name: Docker build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: ${{ github.event_name != 'pull_request' }}\n          tags: bretfisher/docker-ci-automation:02\n#NEW: (START) ##########################################################\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n#NEW: (END) ############################################################"
  },
  {
    "path": ".github/workflows/03-add-multi-platform.yaml",
    "content": "---\nname: 03 Build with Multi-Platform\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n    steps:\n\n#NEW: (START) ##########################################################\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n#NEW: (END) ############################################################\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n            \n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      \n      - name: Docker build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: ${{ github.event_name != 'pull_request' }}\n          tags: bretfisher/docker-ci-automation:03\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n#NEW: (START) ##########################################################\n          platforms: linux/amd64,linux/arm64,linux/arm/v7\n#NEW: (END) ############################################################\n"
  },
  {
    "path": ".github/workflows/04-add-metadata.yaml",
    "content": "---\nname: 04 Build with Metadata\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n    steps:\n\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n#NEW: (START) ##########################################################\n      - name: Docker meta\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=04\n            type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n            type=ref,event=pr\n            type=ref,event=branch\n            type=semver,pattern={{version}}\n#NEW: (END) ############################################################\n      \n      - name: Docker build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n#NEW: (START) ##########################################################\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n#NEW: (END) ############################################################\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/05-add-comment.yaml",
    "content": "---\nname: 05 Build and Comment\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n\n#NEW: (START) ##########################################################\n    permissions:\n      pull-requests: write # needed to create and update comments in PRs\n#NEW: (END) ############################################################\n\n    steps:\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Docker meta\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=05\n            type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n            type=ref,event=pr\n            type=ref,event=branch\n            type=semver,pattern={{version}}\n      \n      - name: Docker build\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: false # false for this demo to prevent overwriting image tags of other examples\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n\n\n#NEW: (START) ##########################################################\n        # If PR, put image tags in the PR comments\n        # from https://github.com/marketplace/actions/create-or-update-comment\n      - name: Find comment for image tags\n        uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e #v3.1.0\n        if: github.event_name == 'pull_request'\n        id: fc\n        with:\n          issue-number: ${{ github.event.pull_request.number }}\n          comment-author: 'github-actions[bot]'\n          body-includes: Docker image tag(s) pushed\n      \n        # If PR, put image tags in the PR comments\n      - name: Create or update comment for image tags\n        uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 #v4.0.0\n        if: github.event_name == 'pull_request'\n        with:\n          comment-id: ${{ steps.fc.outputs.comment-id }}\n          issue-number: ${{ github.event.pull_request.number }}\n          body: |\n            Docker image tag(s) pushed:\n            ```text\n            ${{ steps.docker_meta.outputs.tags }}\n            ```\n\n            Labels added to images:\n            ```text\n            ${{ steps.docker_meta.outputs.labels }}\n            ```\n          edit-mode: replace\n#NEW: (END) ############################################################\n"
  },
  {
    "path": ".github/workflows/06-add-cve-scanning.yaml",
    "content": "---\nname: 06 Build and Scan\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n    \n    steps:\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Build and export to Docker\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: false\n          load: true # Export to Docker Engine rather than pushing to a registry\n          tags: ${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n\n#NEW: (START) ##########################################################\n      - name: Run Trivy for all CVEs (non-blocking)\n        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master\n        with:\n          image-ref: ${{ github.run_id }}\n          exit-code: 0\n          format: table \n#NEW: (END) ############################################################\n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=06\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/07-add-cve-scanning-adv.yaml",
    "content": "---\nname: 07 Build and Scan + Report\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n\n#NEW: (START) ##########################################################\n    permissions:\n      contents: read # for actions/checkout to fetch code\n      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results\n#NEW: (END) ############################################################\n\n    steps:\n\n#NEW: (START) ##########################################################\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n#NEW: (END) ############################################################\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Build and export to Docker\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: false\n          load: true # Export to Docker Engine rather than pushing to a registry\n          tags: ${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n\n      - name: Run Trivy for all CVEs (non-blocking)\n        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master\n        with:\n          image-ref: ${{ github.run_id }}\n          format: table \n          exit-code: 0\n\n#NEW: (START) ##########################################################\n      - name: Run Trivy for HIGH,CRITICAL CVEs and report (blocking)\n        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master\n        with:\n          image-ref: ${{ github.run_id }}\n          exit-code: 1\n          ignore-unfixed: true\n          vuln-type: 'os,library'\n          severity: 'HIGH,CRITICAL'\n          format: 'sarif'\n          output: 'trivy-results.sarif'\n      \n      - name: Upload Trivy scan results to GitHub Security tab\n        uses: github/codeql-action/upload-sarif@5c8a8a642e79153f5d047b10ec1cba1d1cc65699 #v3.35.1\n        if: always()\n        with:\n          sarif_file: 'trivy-results.sarif'\n#NEW: (END) ############################################################\n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=07\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/08-add-unit-test.yaml",
    "content": "---\nname: 08 Build and Unit Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n    steps:\n\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n#NEW: (START) ##########################################################\n      - name: Build and export to Docker\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: false\n          load: true # Export to Docker Engine rather than pushing to a registry\n          tags: ${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n\n        # for simple tests (npm test, etc.) just run a local image in docker\n      - name: Unit Testing in Docker\n        run: |\n          docker run --rm ${{ github.run_id }} echo \"run test commands here\"\n#NEW: (END) ############################################################\n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=08\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/09-add-integration-test.yaml",
    "content": "---\nname: 09 Build and Integration Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n\n    steps:\n\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Build and export to Docker\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: false\n          load: true # Export to Docker Engine rather than pushing to a registry\n          tags: ${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n\n#NEW: (START) ############################################################  \n        # for more advanced tests, use docker compose with `depends_on`\n          # NOTE: GHA and other CIs can also run dependency containers on their own\n          # GHA `services:` can do this if you're trying to avoid docker compose\n      - name: Test healthcheck in Docker Compose\n        run: |\n          export TESTING_IMAGE=\"${{ github.run_id }}\"\n          docker compose -f docker-compose.test.yml up --exit-code-from sut\n#NEW: (END) ############################################################  \n\n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=09\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/10-add-k8s-test.yaml",
    "content": "---\nname: 10 Build and Smoke Test\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n  build-image:\n    name: Build Images\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: write # needed to push docker image to ghcr.io\n\n    steps:\n\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n#NEW: (START) ############################################################\n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      \n      - name: Build and Push to GHCR\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n\n      - uses: AbsaOSS/k3d-action@4e8b3239042be1dc0aed6c5eb80c13b18200fc79 #v2.4.0\n        with:\n          cluster-name: \"test-cluster-1\"\n          args: >-\n            --agents 1\n            --no-lb\n            --k3s-arg \"--no-deploy=traefik,servicelb,metrics-server@server:*\"\n      \n      - name: Smoke test deployment in k3d Kubernetes\n        run: |\n          kubectl create secret docker-registry regcred \\\n            --docker-server=https://ghcr.io \\\n            --docker-username=${{ github.actor }} \\\n            --docker-password=${{ secrets.GITHUB_TOKEN }}\n          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:\"$GITHUB_RUN_ID\"\n          envsubst < manifests/deployment.yaml  | kubectl apply -f -\n          kubectl rollout status deployment myapp\n          kubectl exec deploy/myapp -- curl --fail localhost\n#NEW: (END) ############################################################  \n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation,ghcr.io/bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=10\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n"
  },
  {
    "path": ".github/workflows/99-parallelize-jobs.yaml",
    "content": "---\nname: 99 Parallelize Jobs\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n\njobs:\n# FIRST JOB #######################################################################   \n  build-test-image:\n    name: Build Image for Testing\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: write # needed to push docker image to ghcr.io\n\n    steps:\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      \n      - name: Build and Push to GHCR\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}\n          target: test\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          platforms: linux/amd64\n    \n # NEXT JOB #######################################################################   \n  test-unit:\n    name: Unit tests in Docker\n    needs: [build-test-image]\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: read\n      \n    steps:\n      \n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      \n      - name: Unit Testing in Docker\n        run: docker run --rm ghcr.io/bretfisher/docker-ci-automation:\"$GITHUB_RUN_ID\" echo \"run test commands here\"\n\n# NEXT JOB #######################################################################   \n  test-integration:\n    name: Integration tests in Compose\n    needs: [build-test-image]\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: read\n\n    steps:\n\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      \n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Test healthcheck in Docker Compose\n        run: |\n          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:\"$GITHUB_RUN_ID\"\n          echo Testing image: \"$TESTING_IMAGE\"\n          docker compose -f docker-compose.test.yml up --exit-code-from sut\n\n# NEXT JOB #######################################################################   \n  test-k3d:\n    name: Test Deployment in Kubernetes\n    needs: [build-test-image]\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: read\n\n    steps:\n\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n      \n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - uses: AbsaOSS/k3d-action@4e8b3239042be1dc0aed6c5eb80c13b18200fc79 #v2.4.0\n        with:\n          cluster-name: \"test-cluster-1\"\n          args: >-\n            --agents 1\n            --no-lb\n            --k3s-arg \"--no-deploy=traefik,servicelb,metrics-server@server:*\"\n      \n      - name: Smoke test deployment in k3d Kubernetes\n        run: |\n          kubectl create secret docker-registry regcred \\\n            --docker-server=https://ghcr.io \\\n            --docker-username=${{ github.actor }} \\\n            --docker-password=${{ secrets.GITHUB_TOKEN }}\n          export TESTING_IMAGE=ghcr.io/bretfisher/docker-ci-automation:\"$GITHUB_RUN_ID\"\n          envsubst < manifests/deployment.yaml  | kubectl apply -f -\n          kubectl rollout status deployment myapp\n          kubectl exec deploy/myapp -- curl --fail localhost\n\n# NEXT JOB #######################################################################   \n  scan-image:\n    name: Scan Image with Trivy\n    needs: [build-test-image]\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: read # for actions/checkout to fetch code\n      packages: read # needed to pull docker image to ghcr.io\n      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results\n\n    steps:\n\n      - name: Checkout git repo\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2\n      \n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n          \n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Pull image to scan\n        run: docker pull ghcr.io/bretfisher/docker-ci-automation:\"$GITHUB_RUN_ID\"\n        \n      - name: Run Trivy for all CVEs (non-blocking)\n        uses: aquasecurity/trivy-action@264c9c5e188ea085e7377fd77abd17bfbd4e5926 #master\n        with:\n          image-ref: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}\n          format: table\n          exit-code: 0\n\n      # NOTE: disabled to avoid running twice and overwriting 07-add-cve-scanning-adv.yaml\n      # - name: Run Trivy for HIGH,CRITICAL CVEs and report (blocking)\n      #   uses: aquasecurity/trivy-action@master\n      #   with:\n      #     image-ref: ghcr.io/bretfisher/docker-ci-automation:${{ github.run_id }}\n      #     exit-code: 1\n      #     ignore-unfixed: true\n      #     vuln-type: 'os,library'\n      #     severity: 'HIGH,CRITICAL'\n      #     format: 'sarif'\n      #     output: 'trivy-results.sarif'\n      \n      # - name: Upload Trivy scan results to GitHub Security tab\n      #   uses: github/codeql-action/upload-sarif@v1\n      #   if: always()\n      #   with:\n      #     sarif_file: 'trivy-results.sarif'\n\n# NEXT JOB #######################################################################   \n  build-final-image:\n    name: Build Final Image\n    needs: [test-unit, test-integration, test-k3d, scan-image]\n    runs-on: ubuntu-latest\n\n    permissions:\n      packages: write # needed to push docker image to ghcr.io\n      pull-requests: write # needed to create and update comments in PRs\n\n    steps:\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a #v4.0.0\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd #v4.0.0\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          username: ${{ secrets.DOCKERHUB_USERNAME }}\n          password: ${{ secrets.DOCKERHUB_TOKEN }}\n\n      - name: Login to ghcr.io registry\n        uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Docker Metadata for Final Image Build\n        id: docker_meta\n        uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #v6.0.0\n        with:\n          images: bretfisher/docker-ci-automation,ghcr.io/bretfisher/docker-ci-automation\n          flavor: |\n            latest=false\n          tags: |\n            type=raw,value=99\n          # comment these out on all but 04-add-metadata.yaml to avoid overwriting image tags\n          # type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}\n          # type=ref,event=pr\n          # type=ref,event=branch\n          # type=semver,pattern={{version}}\n      \n      - name: Docker Build and Push to GHCR and Docker Hub\n        uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f #v7.1.0\n        with:\n          push: true\n          tags: ${{ steps.docker_meta.outputs.tags }}\n          labels: ${{ steps.docker_meta.outputs.labels }}\n          cache-from: type=gha\n          cache-to: type=gha,mode=max\n          # comma seperated list of what OS and architechtures to build for (in parallel)\n          # default is linux/amd64 (the OS of the runner) but you can add more\n          # adding linux/arm64 is recommended for Apple Silicon, Raspberry Pi, AWS Graviton, etc.\n          # linux/arm/v7 is for 32-bit ARM devices like Raspberry Pi 2/3\n          platforms: linux/amd64,linux/arm64\n\n        # If PR, put image tags in the PR comments\n        # from https://github.com/marketplace/actions/create-or-update-comment\n        # These are commented out to avoid conflicting with 05-add-comments.yaml example\n      # - name: Find comment for image tags\n      #   uses: peter-evans/find-comment@v1\n      #   if: github.event_name == 'pull_request'\n      #   id: fc\n      #   with:\n      #     issue-number: ${{ github.event.pull_request.number }}\n      #     comment-author: 'github-actions[bot]'\n      #     body-includes: Docker image tag(s) pushed\n      \n      #   # If PR, put image tags in the PR comments\n      # - name: Create or update comment for image tags\n      #   uses: peter-evans/create-or-update-comment@v1\n      #   if: github.event_name == 'pull_request'\n      #   with:\n      #     comment-id: ${{ steps.fc.outputs.comment-id }}\n      #     issue-number: ${{ github.event.pull_request.number }}\n      #     body: |\n      #       Docker image tag(s) pushed:\n      #       ```text\n      #       ${{ steps.docker_meta.outputs.tags }}\n      #       ```\n\n      #       Labels added to images:\n      #       ```text\n      #       ${{ steps.docker_meta.outputs.labels }}\n      #       ```\n      #     edit-mode: replace\n"
  },
  {
    "path": ".github/workflows/call-super-linter.yaml",
    "content": "---\n# template source: https://github.com/bretfisher/super-linter-workflow/blob/main/templates/call-super-linter.yaml\nname: Lint Code Base\n\non:\n  # run anytime a PR is merged to main or a direct push to main\n  push:\n    branches: [main]\n\n  # run on any push to a PR branch\n  pull_request:\n\n# cancel any previously-started, yet still active runs of this workflow on the same branch\nconcurrency:\n  group: ${{ github.ref }}-${{ github.workflow }}\n  cancel-in-progress: true\n\n# reset permissions to none at the workflow level\n# we'll set them at the job level below\npermissions: {}\n\njobs:\n  call-super-linter:\n    name: Call Super-Linter\n\n    permissions:\n      contents: read # clone the repository to lint\n      pull-requests: write # create a summary comment in PR\n      statuses: write # read/write to repository custom statuses\n\n    ### use Reusable Workflows to call my workflow remotely\n    ### https://docs.github.com/en/actions/learn-github-actions/reusing-workflows\n    ### you can also call workflows from inside the same repository via file path\n\n    # FIXME: customize uri to point to your own reusable linter repository\n    # NOTE: zizmor scanner rule ignore added because we control sha pins via reusable workflow, not calling workflow\n    uses: bretfisher/super-linter-workflow/.github/workflows/reusable-super-linter.yaml@main # zizmor: ignore[unpinned-uses]\n\n\n    ### Optional settings examples\n\n    # with:\n    ### 1. Remember .github/super-linter.env is injected for setting linter on/off\n\n    ### 2. For a DevOps-focused repository. Prevents some code-language linters from running\n    ### defaults to false\n    # devops-only: false\n\n    ### 3. A regex to exclude files from linting\n    ### defaults to empty\n    # filter-regex-exclude: html/.*\n    #\n    ### 4. Additional environment variables to pass to super-linter (one per line)\n    # extra-envs: |\n    #   VALIDATE_DOCKERFILE=false\n    #   VALIDATE_JSCPD=false\n    #   VALIDATE_TRIVY=false\n"
  },
  {
    "path": ".gitignore",
    "content": "TODO-*.yaml"
  },
  {
    "path": "Dockerfile",
    "content": "# sample dockerfile for testing docker builds\nFROM nginx:1.20-alpine as base\n\nRUN apk add --no-cache curl\n\nWORKDIR /test\n\nCOPY . .\n\n#########################\nFROM base as test\n\n#layer test tools and assets on top as optional test stage\nRUN apk add --no-cache apache2-utils\n\n\n#########################\nFROM base as final\n\n# this layer gets built by default unless you set target to test\n"
  },
  {
    "path": "LICENSE",
    "content": "This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <https://unlicense.org>\n"
  },
  {
    "path": "README.md",
    "content": "# Automation with Docker for CI Workflows\n\n[![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)\n\n> For Docker Community All Hands 2022\n\n[![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)\n\nWatch the walkthrough of this repo: [https://www.youtube.com/watch?v=aZzV6X7XhyI](https://www.youtube.com/watch?v=aZzV6X7XhyI)\n\nSee this repositories' [`.github/workflows`](.github/workflows) directory for the below example workflows, ordered by number, simple to complex.\n\nThese examples are focused on five of Docker's [official GitHub Actions](https://github.com/marketplace?type=actions&query=publisher%3Adocker+).\n\nThese examples are based on three workflow diagrams on progressively more complex automation pipelines:\n\n1. [Basic code PR automation workflow](diagrams/basic-code-pr.png)\n2. [Intermediate code PR automation workflow](diagrams/intermediate-code-pr.png)\n3. [Advanced code PR automation workflow](diagrams/advanced-code-pr.png)\n\nI also have a [LIVE course on learning GitHub Actions for DevOps automation and Argo CD](https://bret.courses/autodeploy) for GitOps-style deployments.\n\n## Example Workflows\n\n1. Basic Docker build\n2. Adding BuildKit cache\n3. Adding multi-platform builds\n4. Adding metadata to images\n5. Adding comments with image tags to PRs\n6. Adding CVE scanning\n7. Adding CVE security reporting\n8. Adding unit testing\n9. Adding integration testing\n10. Adding Kubernetes smoke tests\n11. Adding job parallelizing for mucho speed\n\n## GitHub Actions shown in these examples\n\n- [Docker Login](https://github.com/marketplace/actions/docker-login)\n- [Docker Setup Buildx](https://github.com/marketplace/actions/docker-setup-buildx)\n- [Docker Setup QEMU](https://github.com/marketplace/actions/docker-setup-qemu)\n- [Docker Metadata](https://github.com/marketplace/actions/docker-metadata-action)\n- [Docker Build and Push](https://github.com/marketplace/actions/build-and-push-docker-images)\n- [Aqua Security Trivy CVE Scan](https://github.com/marketplace/actions/aqua-security-trivy)\n- [Super-Linter](https://github.com/marketplace/actions/super-linter)\n- [Setup k3d](https://github.com/marketplace/actions/absaoss-k3d-action)\n- [Find Comment](https://github.com/marketplace/actions/find-comment)\n- [Create or Update Comment](https://github.com/marketplace/actions/create-or-update-comment)\n\n## This repository is part of my example DevOps repos on GitHub Actions\n\n- [bretfisher/github-actions-templates](https://github.com/BretFisher/github-actions-templates) - Main reusable templates repository\n- [bretfisher/super-linter-workflow](https://github.com/BretFisher/super-linter-workflow) - Reusable linter workflow\n- [bretfisher/docker-build-workflow](https://github.com/BretFisher/docker-build-workflow)- Reusable docker build workflow\n- (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\n- [My full list of container examples and tools](https://github.com/bretfisher)\n\n## More reading\n\n[Docker Build/Push Action advanced examples](https://github.com/docker/build-push-action/tree/master/docs/advanced)\n[My full list of container examples and tools](https://github.com/bretfisher)\n\n## 🎉🎉🎉 Join my container DevOps community 🎉🎉🎉\n\n- [My \"Vital DevOps\" Discord server](https://devops.fan)\n- [My weekly YouTube Live show](https://bret.live)\n- [My courses and coupons](https://www.bretfisher.com/courses)\n"
  },
  {
    "path": "docker-compose.test.yml",
    "content": "services:\n  allhands22:\n    image: \"${TESTING_IMAGE}\"\n  \n  postgres:\n    image: postgres\n    environment:\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: postgres\n    volumes:\n      - ./healthchecks:/healthchecks\n    healthcheck:\n      test: /healthchecks/postgres-healthcheck\n      interval: \"5s\"\n  sut:\n    image: \"${TESTING_IMAGE}\"\n    depends_on:\n      allhands22:\n        condition: service_started\n      postgres:\n        condition: service_healthy\n    # run all your tests here against the allhands22 service\n    command: curl --fail http://allhands22:80 || exit 1"
  },
  {
    "path": "healthchecks/postgres-healthcheck",
    "content": "#!/bin/bash\nset -eo pipefail\n\nhost=\"$(hostname -i || echo '127.0.0.1')\"\nuser=\"${POSTGRES_USER:-postgres}\"\ndb=\"${POSTGRES_DB:-$POSTGRES_USER}\"\nexport PGPASSWORD=\"${POSTGRES_PASSWORD:-}\"\n\nargs=(\n\t# force postgres to not use the local unix socket (test \"external\" connectibility)\n\t--host \"$host\"\n\t--username \"$user\"\n\t--dbname \"$db\"\n\t--quiet --no-align --tuples-only\n)\n\nif select=\"$(echo 'SELECT 1' | psql \"${args[@]}\")\" && [ \"$select\" = '1' ]; then\n\texit 0\nfi\n\nexit 1"
  },
  {
    "path": "manifests/deployment.yaml",
    "content": "# kubernetes deployment\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: myapp\n  labels:\n    app: myapp\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: myapp\n  template:\n    metadata:\n      labels:\n        app: myapp\n    spec:\n      imagePullSecrets:\n        - name: regcred\n      containers:\n        - name: myapp\n          image: \"${TESTING_IMAGE}\"\n          imagePullPolicy: IfNotPresent\n"
  }
]