diff --git a/.github/actions/determine-composer-version/action.yaml b/.github/actions/determine-composer-version/action.yaml index 1ed3b09..7f230cc 100644 --- a/.github/actions/determine-composer-version/action.yaml +++ b/.github/actions/determine-composer-version/action.yaml @@ -4,7 +4,7 @@ name: "Determine composer version from Dockerfile" -description: "Determines the composer version from a Dockerfile and exports it as COMPOSER_VERSION_MAJOR, COMPOSER_VERSION_MAJOR_MINOR, and COMPOSER_VERSION_MAJOR_MINOR_PATCH environment variables." +description: "Determines the composer version from a Dockerfile and exposes it as major, major-minor, and major-minor-patch step outputs." inputs: working-directory: @@ -12,14 +12,29 @@ inputs: description: "Which directory to use as working directory" required: true +outputs: + major: + description: "Composer major version (e.g. 2)" + value: ${{ steps.determine.outputs.major }} + major-minor: + description: "Composer major.minor version (e.g. 2.8)" + value: ${{ steps.determine.outputs.major-minor }} + major-minor-patch: + description: "Composer major.minor.patch version (e.g. 2.8.1)" + value: ${{ steps.determine.outputs.major-minor-patch }} + runs: using: "composite" steps: - name: "Determine composer version from Dockerfile" + id: determine run: | - echo "COMPOSER_VERSION_MAJOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(-RC\d+)?' Dockerfile | cut -d '.' -f 1)" >> $GITHUB_ENV - echo "COMPOSER_VERSION_MAJOR_MINOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(-RC\d+)?' Dockerfile | cut -d '.' -f 1,2)" >> $GITHUB_ENV - echo "COMPOSER_VERSION_MAJOR_MINOR_PATCH=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(-RC\d+)?' Dockerfile)" >> $GITHUB_ENV + version="$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(-RC\d+)?' Dockerfile)" + { + echo "major=$(echo "$version" | cut -d '.' -f 1)" + echo "major-minor=$(echo "$version" | cut -d '.' -f 1,2)" + echo "major-minor-patch=$version" + } >> "$GITHUB_OUTPUT" shell: "bash" working-directory: "${{ inputs.working-directory }}" diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..177b067 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + cooldown: + default-days: 7 diff --git a/.github/workflows/1.10.yaml b/.github/workflows/1.10.yaml index 3c2486d..6c24eed 100644 --- a/.github/workflows/1.10.yaml +++ b/.github/workflows/1.10.yaml @@ -20,9 +20,17 @@ env: GHCR_SLUG: ghcr.io/composer/docker DIRECTORY: '1.10' +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prepare: + name: "Prepare metadata" runs-on: ubuntu-latest @@ -37,16 +45,19 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Determine Composer version from Dockerfile + id: composer-version uses: ./.github/actions/determine-composer-version with: working-directory: ${{ env.DIRECTORY }} - name: Docker metadata (full image) id: meta-full - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -55,8 +66,8 @@ jobs: flavor: | latest=false tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} labels: | org.opencontainers.image.vendor=Composer org.opencontainers.image.title=Composer @@ -64,7 +75,7 @@ jobs: - name: Docker metadata (binary-only image) id: meta-bin - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -74,18 +85,23 @@ jobs: latest=false suffix=-bin tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} labels: | org.opencontainers.image.vendor=Composer org.opencontainers.image.title=Composer org.opencontainers.image.description=Image with Composer binary only build: + name: "Build images" runs-on: ubuntu-latest timeout-minutes: 20 + permissions: + contents: read + packages: write # pushes image layers to ghcr.io via GITHUB_TOKEN + needs: - prepare @@ -108,31 +124,34 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Prepare + env: + PLATFORM: ${{ matrix.platform }} run: | - platform=${{ matrix.platform }} - echo "PLATFORM_SLUG=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_SLUG=${PLATFORM//\//-}" >> "$GITHUB_ENV" - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 with: platforms: ${{ matrix.platform }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} @@ -140,7 +159,7 @@ jobs: - name: Login to Github Container Registry if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -148,7 +167,7 @@ jobs: - name: Build full image id: build-full - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: binary-with-runtime @@ -158,7 +177,7 @@ jobs: - name: Build binary-only image id: build-bin - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: standalone-binary @@ -167,15 +186,16 @@ jobs: outputs: type=image,"name=${{ env.DOCKERHUB_SLUG }},${{ env.ECR_SLUG }},${{ env.GHCR_SLUG }}",push-by-digest=true,name-canonical=true,push=${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }} - name: Export digests + env: + DIGEST_FULL: ${{ steps.build-full.outputs.digest }} + DIGEST_BIN: ${{ steps.build-bin.outputs.digest }} run: | mkdir -p /tmp/digests/{full,bin} - digest="${{ steps.build-full.outputs.digest }}" - touch "/tmp/digests/full/${digest#sha256:}" - digest="${{ steps.build-bin.outputs.digest }}" - touch "/tmp/digests/bin/${digest#sha256:}" + touch "/tmp/digests/full/${DIGEST_FULL#sha256:}" + touch "/tmp/digests/bin/${DIGEST_BIN#sha256:}" - name: Upload digests - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: digests-${{ env.PLATFORM_SLUG }} path: | @@ -185,11 +205,16 @@ jobs: retention-days: 1 merge: + name: "Merge & push manifests" if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read + packages: write # pushes the manifest list to ghcr.io via GITHUB_TOKEN + needs: - prepare - build @@ -197,30 +222,30 @@ jobs: steps: - name: Download digests - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: /tmp/digests pattern: digests-* merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} password: ${{ secrets.AWS_ECR_SECRET_KEY }} - name: Login to Github Container Registry - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -231,21 +256,21 @@ jobs: env: JSON: ${{ needs.prepare.outputs.full-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) - name: Create manifest list for binary-only image and push working-directory: /tmp/digests/bin env: JSON: ${{ needs.prepare.outputs.bin-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) diff --git a/.github/workflows/2.2.yaml b/.github/workflows/2.2.yaml index f58c825..293760a 100644 --- a/.github/workflows/2.2.yaml +++ b/.github/workflows/2.2.yaml @@ -20,9 +20,17 @@ env: GHCR_SLUG: ghcr.io/composer/docker DIRECTORY: '2.2' +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prepare: + name: "Prepare metadata" runs-on: ubuntu-latest @@ -37,16 +45,19 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Determine Composer version from Dockerfile + id: composer-version uses: ./.github/actions/determine-composer-version with: working-directory: ${{ env.DIRECTORY }} - name: Docker metadata (full image) id: meta-full - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -55,8 +66,8 @@ jobs: flavor: | latest=false tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} labels: | org.opencontainers.image.vendor=Composer org.opencontainers.image.title=Composer @@ -64,7 +75,7 @@ jobs: - name: Docker metadata (binary-only image) id: meta-bin - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -74,18 +85,23 @@ jobs: latest=false suffix=-bin tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} labels: | org.opencontainers.image.vendor=Composer org.opencontainers.image.title=Composer org.opencontainers.image.description=Image with Composer binary only build: + name: "Build images" runs-on: ubuntu-latest timeout-minutes: 20 + permissions: + contents: read + packages: write # pushes image layers to ghcr.io via GITHUB_TOKEN + needs: - prepare @@ -108,31 +124,34 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Prepare + env: + PLATFORM: ${{ matrix.platform }} run: | - platform=${{ matrix.platform }} - echo "PLATFORM_SLUG=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_SLUG=${PLATFORM//\//-}" >> "$GITHUB_ENV" - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 with: platforms: ${{ matrix.platform }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} @@ -140,7 +159,7 @@ jobs: - name: Login to Github Container Registry if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -148,7 +167,7 @@ jobs: - name: Build full image id: build-full - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: binary-with-runtime @@ -158,7 +177,7 @@ jobs: - name: Build binary-only image id: build-bin - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: standalone-binary @@ -167,15 +186,16 @@ jobs: outputs: type=image,"name=${{ env.DOCKERHUB_SLUG }},${{ env.ECR_SLUG }},${{ env.GHCR_SLUG }}",push-by-digest=true,name-canonical=true,push=${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }} - name: Export digests + env: + DIGEST_FULL: ${{ steps.build-full.outputs.digest }} + DIGEST_BIN: ${{ steps.build-bin.outputs.digest }} run: | mkdir -p /tmp/digests/{full,bin} - digest="${{ steps.build-full.outputs.digest }}" - touch "/tmp/digests/full/${digest#sha256:}" - digest="${{ steps.build-bin.outputs.digest }}" - touch "/tmp/digests/bin/${digest#sha256:}" + touch "/tmp/digests/full/${DIGEST_FULL#sha256:}" + touch "/tmp/digests/bin/${DIGEST_BIN#sha256:}" - name: Upload digests - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: digests-${{ env.PLATFORM_SLUG }} path: | @@ -185,11 +205,16 @@ jobs: retention-days: 1 merge: + name: "Merge & push manifests" if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read + packages: write # pushes the manifest list to ghcr.io via GITHUB_TOKEN + needs: - prepare - build @@ -197,30 +222,30 @@ jobs: steps: - name: Download digests - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: /tmp/digests pattern: digests-* merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} password: ${{ secrets.AWS_ECR_SECRET_KEY }} - name: Login to Github Container Registry - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -231,21 +256,21 @@ jobs: env: JSON: ${{ needs.prepare.outputs.full-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) - name: Create manifest list for binary-only image and push working-directory: /tmp/digests/bin env: JSON: ${{ needs.prepare.outputs.bin-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) diff --git a/.github/workflows/latest.yaml b/.github/workflows/latest.yaml index 4ed4a5c..7f60a8e 100644 --- a/.github/workflows/latest.yaml +++ b/.github/workflows/latest.yaml @@ -20,9 +20,17 @@ env: GHCR_SLUG: ghcr.io/composer/docker DIRECTORY: latest +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: prepare: + name: "Prepare metadata" runs-on: ubuntu-latest @@ -37,16 +45,19 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Determine Composer version from Dockerfile + id: composer-version uses: ./.github/actions/determine-composer-version with: working-directory: ${{ env.DIRECTORY }} - name: Docker metadata (full image) id: meta-full - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -55,9 +66,9 @@ jobs: flavor: | latest=false tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}},value=${{ steps.composer-version.outputs.major-minor-patch }} latest labels: | org.opencontainers.image.vendor=Composer @@ -66,7 +77,7 @@ jobs: - name: Docker metadata (binary-only image) id: meta-bin - uses: docker/metadata-action@v6 + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 with: images: | ${{ env.DOCKERHUB_SLUG }} @@ -76,9 +87,9 @@ jobs: latest=false suffix=-bin tags: | - type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} - type=semver,pattern={{major}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }} + type=semver,pattern={{version}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.composer-version.outputs.major-minor-patch }} + type=semver,pattern={{major}},value=${{ steps.composer-version.outputs.major-minor-patch }} latest labels: | org.opencontainers.image.vendor=Composer @@ -86,10 +97,15 @@ jobs: org.opencontainers.image.description=Image with Composer binary only build: + name: "Build images" runs-on: ubuntu-latest timeout-minutes: 20 + permissions: + contents: read + packages: write # pushes image layers to ghcr.io via GITHUB_TOKEN + needs: - prepare @@ -112,31 +128,34 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Prepare + env: + PLATFORM: ${{ matrix.platform }} run: | - platform=${{ matrix.platform }} - echo "PLATFORM_SLUG=${platform//\//-}" >> $GITHUB_ENV + echo "PLATFORM_SLUG=${PLATFORM//\//-}" >> "$GITHUB_ENV" - name: Set up QEMU - uses: docker/setup-qemu-action@v4 + uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 with: platforms: ${{ matrix.platform }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} @@ -144,7 +163,7 @@ jobs: - name: Login to Github Container Registry if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -152,7 +171,7 @@ jobs: - name: Build full image id: build-full - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: binary-with-runtime @@ -162,7 +181,7 @@ jobs: - name: Build binary-only image id: build-bin - uses: docker/build-push-action@v7 + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: context: ${{ env.DIRECTORY }} target: standalone-binary @@ -171,15 +190,16 @@ jobs: outputs: type=image,"name=${{ env.DOCKERHUB_SLUG }},${{ env.ECR_SLUG }},${{ env.GHCR_SLUG }}",push-by-digest=true,name-canonical=true,push=${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }} - name: Export digests + env: + DIGEST_FULL: ${{ steps.build-full.outputs.digest }} + DIGEST_BIN: ${{ steps.build-bin.outputs.digest }} run: | mkdir -p /tmp/digests/{full,bin} - digest="${{ steps.build-full.outputs.digest }}" - touch "/tmp/digests/full/${digest#sha256:}" - digest="${{ steps.build-bin.outputs.digest }}" - touch "/tmp/digests/bin/${digest#sha256:}" + touch "/tmp/digests/full/${DIGEST_FULL#sha256:}" + touch "/tmp/digests/bin/${DIGEST_BIN#sha256:}" - name: Upload digests - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: digests-${{ env.PLATFORM_SLUG }} path: | @@ -189,11 +209,16 @@ jobs: retention-days: 1 merge: + name: "Merge & push manifests" if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read + packages: write # pushes the manifest list to ghcr.io via GITHUB_TOKEN + needs: - prepare - build @@ -201,30 +226,30 @@ jobs: steps: - name: Download digests - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: path: /tmp/digests pattern: digests-* merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - name: Login to Docker Hub - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to Amazon Public ECR - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: public.ecr.aws username: ${{ secrets.AWS_ECR_ACCESS_KEY }} password: ${{ secrets.AWS_ECR_SECRET_KEY }} - name: Login to Github Container Registry - uses: docker/login-action@v4 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -235,21 +260,21 @@ jobs: env: JSON: ${{ needs.prepare.outputs.full-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) - name: Create manifest list for binary-only image and push working-directory: /tmp/digests/bin env: JSON: ${{ needs.prepare.outputs.bin-json }} run: | - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.ECR_SLUG }}@sha256:%s ' *) - docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \ - $(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *) + docker buildx imagetools create $(jq -cr --arg slug "$DOCKERHUB_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$DOCKERHUB_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$ECR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$ECR_SLUG@sha256:%s " *) + docker buildx imagetools create $(jq -cr --arg slug "$GHCR_SLUG" '.tags | map(select(startswith($slug)) | "--tag " + .) | join(" ")' <<< "$JSON") \ + $(printf "$GHCR_SLUG@sha256:%s " *) diff --git a/.github/workflows/shellcheck.yaml b/.github/workflows/shellcheck.yaml index e34db9e..adcd403 100644 --- a/.github/workflows/shellcheck.yaml +++ b/.github/workflows/shellcheck.yaml @@ -7,12 +7,21 @@ on: - .github/workflows/shellcheck.yaml - '**.sh' +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: shellcheck: name: ShellCheck runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: ShellCheck run: find . -type f -name '*.sh' | grep -v generate-stackbrew-library | xargs shellcheck diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..a589d51 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,35 @@ +name: GitHub Actions Security Analysis with zizmor 🌈 + +on: + push: + branches: + - main + paths: + - '.github/**.yml' + pull_request: + paths: + - '.github/**.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + zizmor: + name: Run zizmor 🌈 + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run zizmor 🌈 + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + with: + advanced-security: false + annotations: true + persona: 'pedantic'