|
5 | 5 | types: [published] |
6 | 6 |
|
7 | 7 | jobs: |
8 | | - build-push-image: |
| 8 | + build: |
9 | 9 | runs-on: ubuntu-latest |
| 10 | + permissions: |
| 11 | + id-token: write |
| 12 | + packages: write |
| 13 | + contents: read |
| 14 | + attestations: write |
| 15 | + env: |
| 16 | + REGISTRY: index.docker.io |
| 17 | + REGISTRY_NAME: fontebasso/php-nginx |
| 18 | + |
| 19 | + outputs: |
| 20 | + VERSION: ${{ steps.vars.outputs.VERSION }} |
| 21 | + MAJOR: ${{ steps.vars.outputs.MAJOR }} |
| 22 | + MINOR: ${{ steps.vars.outputs.MINOR }} |
| 23 | + |
10 | 24 | steps: |
| 25 | + - name: Set up QEMU |
| 26 | + uses: docker/setup-qemu-action@v3 |
| 27 | + |
| 28 | + - name: Set up Docker Buildx |
| 29 | + uses: docker/setup-buildx-action@v3 |
| 30 | + |
| 31 | + - name: Install Syft |
| 32 | + run: | |
| 33 | + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin |
| 34 | +
|
11 | 35 | - name: Publish version env var |
12 | 36 | run: echo "VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV |
13 | 37 |
|
14 | | - - name: checkout code |
15 | | - uses: actions/checkout@v2 |
| 38 | + - name: Checkout code |
| 39 | + uses: actions/checkout@v4 |
16 | 40 |
|
17 | 41 | - name: Login to Docker Hub |
18 | 42 | uses: docker/login-action@v1 |
19 | 43 | with: |
20 | | - username: ${{ secrets.DOCKERHUB_USERNAME }} |
| 44 | + username: fontebasso |
21 | 45 | password: ${{ secrets.DOCKERHUB_TOKEN }} |
22 | 46 |
|
23 | | - - name: Set up QEMU |
24 | | - uses: docker/setup-qemu-action@v1 |
| 47 | + - name: Extract version parts |
| 48 | + id: vars |
| 49 | + run: | |
| 50 | + IFS='.' read -r MAJOR MINOR PATCH <<< "${{ env.VERSION }}" |
| 51 | + echo "MAJOR=$MAJOR" >> $GITHUB_ENV |
| 52 | + echo "MINOR=$MINOR" >> $GITHUB_ENV |
| 53 | + echo "VERSION=${{ env.VERSION }}" >> $GITHUB_OUTPUT |
| 54 | + echo "MAJOR=$MAJOR" >> $GITHUB_OUTPUT |
| 55 | + echo "MINOR=$MINOR" >> $GITHUB_OUTPUT |
25 | 56 |
|
26 | | - - name: Set up Docker Buildx |
27 | | - id: buildx |
28 | | - uses: docker/setup-buildx-action@v1 |
29 | | - |
30 | | - - name: build and push the image |
31 | | - run: | |
32 | | - docker buildx build . \ |
33 | | - --build-arg BUILD_ID=${{ github.run_id }} \ |
34 | | - --build-arg COMMIT_ID=$(git rev-parse --short "$GITHUB_SHA") \ |
35 | | - --tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{ env.VERSION }} \ |
36 | | - --tag ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:latest \ |
37 | | - --platform linux/amd64,linux/arm64 \ |
38 | | - --push |
39 | | -
|
40 | | - - name: Push readme |
41 | | - uses: actionhippie/pushrm@v1 |
42 | | - with: |
43 | | - provider: dockerhub |
44 | | - target: fontebasso/php-nginx |
45 | | - username: ${{ secrets.DOCKERHUB_USERNAME }} |
46 | | - password: ${{ secrets.DOCKERHUB_PASSWORD }} |
47 | | - readme: README.md |
| 57 | + - name: Docker meta |
| 58 | + id: meta |
| 59 | + uses: docker/metadata-action@v5 |
| 60 | + with: |
| 61 | + images: ${{ env.REGISTRY_NAME }} |
| 62 | + tags: | |
| 63 | + ${{ env.VERSION }} |
| 64 | + ${{ env.MAJOR }}.${{ env.MINOR }} |
| 65 | + ${{ env.MAJOR }} |
| 66 | + latest |
| 67 | + annotations: | |
| 68 | + org.opencontainers.image.title=${{ env.REGISTRY_NAME }} |
| 69 | + org.opencontainers.image.description=$(cat README.md) |
| 70 | +
|
| 71 | + - name: Build and push |
| 72 | + id: push |
| 73 | + uses: docker/build-push-action@v6 |
| 74 | + with: |
| 75 | + context: . |
| 76 | + platforms: linux/amd64,linux/arm64 |
| 77 | + tags: ${{ steps.meta.outputs.tags }} |
| 78 | + push: true |
| 79 | + provenance: mode=max |
| 80 | + sbom: true |
| 81 | + build-args: | |
| 82 | + BUILD_ID=${{ github.run_id }} |
| 83 | + COMMIT_ID=$(git rev-parse --short "$GITHUB_SHA") |
| 84 | + |
| 85 | + - name: Extract provenance |
| 86 | + shell: bash |
| 87 | + run: | |
| 88 | + echo $(jq -r '.provenance[]' < $GITHUB_WORKSPACE/.github/actions/buildx/output.json) > provenance.json |
| 89 | +
|
| 90 | + - name: Upload provenance |
| 91 | + uses: actions/upload-artifact@v4 |
| 92 | + with: |
| 93 | + name: provenance |
| 94 | + path: provenance.json |
| 95 | + |
| 96 | + - name: Generate SBOM |
| 97 | + id: sbom |
| 98 | + shell: bash |
| 99 | + run: | |
| 100 | + for tag in $(echo "${{ steps.meta.outputs.tags }}" | grep -Ev '^$' | tr ',' '\n'); do |
| 101 | + for platform in linux/amd64 linux/arm64; do |
| 102 | + digest=$(docker buildx imagetools inspect "${tag}" --raw | jq -r ".manifests[] | select(.platform.architecture==\"${platform##*/}\") | .digest") |
| 103 | + if [ -n "$digest" ]; then |
| 104 | + normalized_tag=$(echo "${tag}_${platform}" | tr ':' '_' | tr '.' '_' | tr '/' '_' | tr '-' '_') |
| 105 | + echo "${normalized_tag}=${digest}" >> digest_mapping.txt |
| 106 | + mkdir -p sbom |
| 107 | + syft "${tag}" -o spdx-json > "sbom/${normalized_tag}.sbom.spdx.json" |
| 108 | + fi |
| 109 | + done |
| 110 | + done |
| 111 | +
|
| 112 | + - name: Upload digest mapping file |
| 113 | + uses: actions/upload-artifact@v4 |
| 114 | + with: |
| 115 | + name: digest_mapping |
| 116 | + path: digest_mapping.txt |
| 117 | + |
| 118 | + - name: Upload SBOM files |
| 119 | + uses: actions/upload-artifact@v4 |
| 120 | + with: |
| 121 | + name: sbom |
| 122 | + path: sbom |
| 123 | + |
| 124 | + sign: |
| 125 | + runs-on: ubuntu-latest |
| 126 | + needs: build |
| 127 | + env: |
| 128 | + REGISTRY_NAME: fontebasso/php-nginx |
| 129 | + |
| 130 | + strategy: |
| 131 | + matrix: |
| 132 | + platform: ["linux/amd64", "linux/arm64"] |
| 133 | + tags: ["latest", "${{ needs.build.outputs.VERSION }}", "${{ needs.build.outputs.MAJOR }}.${{ needs.build.outputs.MINOR }}", "${{ needs.build.outputs.MAJOR }}"] |
| 134 | + |
| 135 | + steps: |
| 136 | + - name: Login to Docker Hub |
| 137 | + uses: docker/login-action@v1 |
| 138 | + with: |
| 139 | + username: fontebasso |
| 140 | + password: ${{ secrets.DOCKERHUB_TOKEN }} |
| 141 | + |
| 142 | + - name: Download digest mapping file |
| 143 | + uses: actions/download-artifact@v4 |
| 144 | + with: |
| 145 | + name: digest_mapping |
| 146 | + |
| 147 | + - name: Prepare |
| 148 | + run: | |
| 149 | + normalized_tag=$(echo "${{ env.REGISTRY_NAME }}:${{ matrix.tags }}_${{ matrix.platform }}" | tr ':' '_' | tr '.' '_' | tr '/' '_' | tr '-' '_') |
| 150 | + TAG_DIGEST=$(grep "^${normalized_tag}=" digest_mapping.txt | cut -d '=' -f 2) |
| 151 | + echo "TAG_DIGEST=${TAG_DIGEST}" >> $GITHUB_ENV |
| 152 | + echo "TAG_NORMALIZED=${normalized_tag}" >> $GITHUB_ENV |
| 153 | +
|
| 154 | + - name: Cosign install |
| 155 | + run: | |
| 156 | + curl -LO https://github.com/sigstore/cosign/releases/download/v2.2.4/cosign-linux-amd64 |
| 157 | + chmod +x cosign-linux-amd64 |
| 158 | + mv cosign-linux-amd64 cosign |
| 159 | +
|
| 160 | + - name: Load Cosign key |
| 161 | + run: | |
| 162 | + echo "${{ secrets.B64_COSIGN_KEY }}" | base64 -d > cosign.key |
| 163 | + echo "${{ secrets.B64_COSIGN_PUB }}" | base64 -d > cosign.pub |
| 164 | +
|
| 165 | + - name: Sign image with Cosign |
| 166 | + run: | |
| 167 | + ./cosign sign --yes --key cosign.key ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }} |
| 168 | + ./cosign verify --key cosign.pub ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }} |
| 169 | +
|
| 170 | + - name: Publish signature Rekor |
| 171 | + run: | |
| 172 | + ./cosign sign --yes --key cosign.key --rekor-url https://rekor.sigstore.dev ${{ env.REGISTRY_NAME }}@${{ env.TAG_DIGEST }} |
0 commit comments