Skip to content

Build and push images #81

Build and push images

Build and push images #81

Workflow file for this run

name: Build and push images
on:
workflow_dispatch:
inputs:
runsOn:
description: 'runs on, default is ubuntu-latest'
dockerhubImageName:
description: 'dockerhub image name, default is dockerhub repository slug, needs start with index.docker.io/'
ghcrImageName:
description: 'ghcr.io image name, default is github repository slug, needs start with ghcr.io/'
awsEcrImageName:
description: 'AWS ECR image name, defaule is aws ecr repository slug, needs start with public.ecr.aws/'
schedule:
# every Wednesday at 3:42 AM(UTC, Beijing time: 11:42 AM)
- cron: '42 3 * * 3'
env:
TRY_MIRRORS: ""
PUBLIC_MIRROR: "https://dl-cdn.alpinelinux.org" # no mirror needed at github actions
jobs:
prepare:
name: Prepare matrix
runs-on: 'ubuntu-latest'
outputs:
tags: ${{ steps.gentasks.outputs.tags }}
images: ${{ steps.gentasks.outputs.images }}
outputs: ${{ steps.gentasks.outputs.outputs }}
steps:
- name: Generate tasks
shell: python3 {0}
id: gentasks
run: |
import os, json
from distutils.version import LooseVersion
phpAlpineVersions = {
"8.4": "3.22",
"8.3": "3.22",
"8.2": "3.22",
"8.1": "3.18",
"8.0": "3.16",
}
extVersions = [
# swoole master branch
("swoole-master", "8.1", None),
# swoole 6.0 branch
("swoole-6.0.2", "8.1", None),
# swoole 5.1 branch
("swoole-5.1.8", "8.0", "8.3"),
# swoole 4.8 branch
("swoole-4.8.13", "8.0", "8.2"),
# swow ci branch
("swow-ci", "8.0", None),
# swow
("swow-1.6.1", "8.0", "8.4"),
]
extraExts = [
"jsonpath",
"parle",
"xlswriter",
]
extraExtTag = "-".join(sorted(extraExts))
githubOutput = open(os.environ["GITHUB_OUTPUT"], "w")
tags = []
index = 0
for phpVer, alpineVer in phpAlpineVersions.items():
for extVersion in extVersions:
ext, minPhpVer, maxPhpVer = extVersion
if minPhpVer and LooseVersion(phpVer) < LooseVersion(minPhpVer):
continue
if maxPhpVer and LooseVersion(phpVer) > LooseVersion(maxPhpVer):
continue
tag = f"{phpVer}-alpine-{alpineVer}-{ext}-{extraExtTag}"
tags.append(tag)
print(f"Add tag {tag}")
index += 1
serialized = json.dumps(tags)
print(f"generated matrix: {serialized}")
githubOutput.write(f"tags={serialized}\n")
images = []
images.append("${{ inputs.ghcrImageName }}" or "ghcr.io/${{ github.repository }}")
if "${{ secrets.DOCKERHUB_CRED }}":
images.append("${{ inputs.dockerhubImageName }}" or "index.docker.io/${{ github.repository }}")
if "${{ secrets.AWS_ECR_CRED }}":
images.append("${{ inputs.awsEcrImageName }}" or "public.ecr.aws/${{ github.repository }}")
imagesString = " ".join(images)
githubOutput.write(f"images={imagesString}\n")
githubOutput.close()
build:
name: ${{ matrix.tag }} build and push
runs-on: "${{ inputs.runsOn || 'ubuntu-latest' }}"
needs: prepare
strategy:
matrix:
tag: ${{ fromJson(needs.prepare.outputs.tags) }}
max-parallel: 5
fail-fast: false
permissions:
contents: write
packages: write
id-token: write
attestations: write
steps:
# checkout source code
- name: Checkout
uses: actions/checkout@v4
- name: Setup buildx oci builder
run: |
set -xeo pipefail
docker buildx inspect buildx-oci-builder ||
docker buildx create \
--driver docker-container \
--driver-opt image=moby/buildkit:master,network=host \
--bootstrap \
--name buildx-oci-builder
docker buildx use buildx-oci-builder
- name: Set up secrets
shell: python3 {0}
id: set-secrets
run: |
import os, json, base64
githubOutput = open(os.environ["GITHUB_OUTPUT"], "w")
fw = open(os.path.expanduser("~/.docker/config.json"), "w")
config = {
"auths": {},
}
# GHCR
cred = base64.b64encode(b'whatever:${{ github.token }}').decode()
config["auths"]["ghcr.io"] = {
"auth": cred,
}
# AWS ECR
cred = "${{ secrets.AWS_ECR_CRED }}"
if cred:
config["auths"]["public.ecr.aws"] = {
"auth": cred,
}
githubOutput.write(f"has_aws_ecr=1\n")
# DockerHub
cred = "${{ secrets.DOCKERHUB_CRED }}"
if cred:
config["auths"]["https://index.docker.io/v1/"] = {
"auth": cred,
}
githubOutput.write(f"has_dockerhub=1\n")
fw.write(json.dumps(config))
fw.close()
- name: Build image
shell: bash
id: build
run: |
GITHUB_TOKEN="${{ github.token }}" \
python -u \
./build.py "${{ matrix.tag }}" \
${{ needs.prepare.outputs.images }} \
--oci \
--arch-suffix \
--gen-metadata \
--push
cat metadata_stripped.json
cat metadata_debuggable.json
digest=$(jq -r '."containerimage.digest"' metadata_stripped.json)
echo "stripped_digest=${digest}" >> "${GITHUB_OUTPUT}"
digest=$(jq -r '."containerimage.digest"' metadata_debuggable.json)
echo "debuggable_digest=${digest}" >> "${GITHUB_OUTPUT}"
# why github donot allow attest multiple images at once?
- name: Generate provenance attestation for stripped image at ghcr.io
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ inputs.ghcrImageName || format('ghcr.io/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.stripped_digest }}
push-to-registry: true
- name: Generate provenance attestation for debuggable image at ghcr.io
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ inputs.ghcrImageName || format('ghcr.io/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.debuggable_digest }}
push-to-registry: true
- name: Generate provenance attestation for stripped image at dockerhub
uses: actions/attest-build-provenance@v2
if: ${{ steps.set-secrets.outputs.has_dockerhub }}
with:
subject-name: ${{ inputs.dockerhubImageName || format('index.docker.io/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.stripped_digest }}
push-to-registry: true
- name: Generate provenance attestation for debuggable image at dockerhub
uses: actions/attest-build-provenance@v2
if: ${{ steps.set-secrets.outputs.has_dockerhub }}
with:
subject-name: ${{ inputs.dockerhubImageName || format('index.docker.io/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.debuggable_digest }}
push-to-registry: true
- name: Generate provenance attestation for stripped image at aws-ecr
uses: actions/attest-build-provenance@v2
if: ${{ steps.set-secrets.outputs.has_aws_ecr }}
with:
subject-name: ${{ inputs.awsEcrImageName || format('public.ecr.aws/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.stripped_digest }}
push-to-registry: true
- name: Generate provenance attestation for debuggable image at aws-ecr
uses: actions/attest-build-provenance@v2
if: ${{ steps.set-secrets.outputs.has_aws_ecr }}
with:
subject-name: ${{ inputs.awsEcrImageName || format('public.ecr.aws/{0}', github.repository) }}
subject-digest: ${{ steps.build.outputs.debuggable_digest }}
push-to-registry: true
- name: Merge images
shell: bash
id: merge
run: |
./.github/workflows/mergeimages.py \
'${{ matrix.tag }}' \
'${{ steps.build.outputs.stripped_digest }}' \
'${{ steps.build.outputs.debuggable_digest }}' \
${{ needs.prepare.outputs.images }}
- name: Generate provenance attestation for merged stripped image at ghcr.io
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.ghcrStrippedDigest }}
with:
subject-name: ${{ inputs.ghcrImageName || format('ghcr.io/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.ghcrStrippedDigest }}
push-to-registry: true
- name: Generate provenance attestation for merged debuggable image at ghcr.io
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.ghcrDebuggableDigest }}
with:
subject-name: ${{ inputs.ghcrImageName || format('ghcr.io/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.ghcrDebuggableDigest }}
push-to-registry: true
- name: Generate provenance attestation for merged stripped image at dockerhub
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.dockerhubStrippedDigest }}
with:
subject-name: ${{ inputs.dockerhubImageName || format('index.docker.io/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.dockerhubStrippedDigest }}
push-to-registry: true
- name: Generate provenance attestation for merged debuggable image at dockerhub
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.dockerhubDebuggableDigest }}
with:
subject-name: ${{ inputs.dockerhubImageName || format('index.docker.io/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.dockerhubDebuggableDigest }}
push-to-registry: true
- name: Generate provenance attestation for merged stripped image at aws-ecr
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.awsEcrStrippedDigest }}
with:
subject-name: ${{ inputs.awsEcrImageName || format('public.ecr.aws/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.awsEcrStrippedDigest }}
push-to-registry: true
- name: Generate provenance attestation for merged debuggable image at aws-ecr
uses: actions/attest-build-provenance@v2
if: ${{ steps.merge.outputs.awsEcrDebuggableDigest }}
with:
subject-name: ${{ inputs.awsEcrImageName || format('public.ecr.aws/{0}', github.repository) }}
subject-digest: ${{ steps.merge.outputs.awsEcrDebuggableDigest }}
push-to-registry: true