Continuous Integration #4088
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Continuous Integration | |
env: | |
DOCKER_IMAGE: wyrihaximusnet/php | |
DOCKER_BUILDKIT: 1 | |
DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING: '{"ghcr.io":"GHCR_TOKEN","docker.io":"HUB_PASSCODE"}' | |
DOCKER_CLI_EXPERIMENTAL: enabled | |
on: | |
push: | |
branches: | |
- master | |
pull_request: | |
schedule: | |
- cron: '13 4 * * *' | |
jobs: | |
supported-alpine-versions: | |
name: Supported Alpine versions | |
runs-on: ubuntu-latest | |
outputs: | |
alpine: ${{ steps.supported-alpine-versions.outputs.versions }} | |
steps: | |
- id: supported-alpine-versions | |
name: Generate Alpine | |
uses: wyrihaximus/github-action-supported-alpine-linux-versions@v1 | |
with: | |
maxVersions: 2 | |
supported-debian-versions: | |
name: Supported Debian versions | |
runs-on: ubuntu-latest | |
outputs: | |
debian: ${{ steps.supported-debian-versions.outputs.versions }} | |
steps: | |
- id: supported-debian-versions | |
name: Generate Debian | |
uses: wyrihaximus/github-action-supported-debian-linux-versions@v1 | |
supported-php-versions: | |
name: Supported PHP versions | |
runs-on: ubuntu-latest | |
outputs: | |
php: ${{ steps.supported-php-versions.outputs.versions }} | |
steps: | |
- id: supported-php-versions | |
name: Generate PHP | |
uses: wyrihaximus/github-action-supported-php-versions@v1 | |
with: | |
upcomingReleases: true | |
supported-arch-matrix: | |
name: Supported processor architectures | |
runs-on: ubuntu-latest | |
outputs: | |
arch: ${{ steps.supported-arch-matrix.outputs.arch }} | |
steps: | |
- uses: actions/checkout@v3 | |
- id: supported-arch-matrix | |
name: Generate Arch | |
run: | | |
echo "arch=[\"amd64\",\"arm64\"]" >> $GITHUB_OUTPUT | |
image-type-matrix: | |
name: Create Image Type Matrix | |
runs-on: ubuntu-latest | |
outputs: | |
type: ${{ steps.image-type-matrix.outputs.type }} | |
steps: | |
- uses: actions/checkout@v1 | |
- id: image-type-matrix | |
name: Generate Type | |
run: | | |
ls Dockerfile-* | jq -csR '. | rtrimstr("\n") | split("\n")' | php -r "echo str_replace('Dockerfile-', '', stream_get_contents(STDIN));" > types.list | |
cat types.list | |
echo "type=$(cat types.list)" >> $GITHUB_OUTPUT | |
exclude-matrix: | |
name: Create Exclude Matrix | |
runs-on: ubuntu-latest | |
outputs: | |
exclude: ${{ steps.exclude-matrix.outputs.exclude }} | |
exclude-push: ${{ steps.exclude-matrix.outputs.exclude-push }} | |
steps: | |
- uses: actions/checkout@v1 | |
- id: exclude-matrix | |
name: Generate Exclude | |
run: | | |
php utils/exclude-list.php | |
image-matrix: | |
name: Create Image Matrix | |
runs-on: ubuntu-latest | |
needs: | |
- supported-alpine-versions | |
- supported-debian-versions | |
- supported-php-versions | |
outputs: | |
image: ${{ steps.image-matrix.outputs.image }} | |
steps: | |
- uses: actions/checkout@v1 | |
- id: image-matrix | |
name: Generate Combined Image Matrix | |
run: | | |
echo "Generate full image list" | |
php utils/all-images.php | |
if [ "${{ github.event_name }}" == "schedule" ] ; then | |
echo "This is a scheduled run, scanning for CVE's" | |
php utils/all-image-tags.php | xargs -I % sh -c 'docker run -v /tmp/trivy:/var/lib/trivy -v /var/run/docker.sock:/var/run/docker.sock -t aquasec/trivy:latest --cache-dir /var/lib/trivy image --exit-code 1 --no-progress $(php -r "echo explode(\"#\", \"%\")[0];") > /dev/null || echo "%|"' >> images_with.cves | |
if [ -s "images_with.cves" ] | |
then | |
echo "Found images with CVE's in them" | |
cat images_with.cves | xargs -I % php -r 'echo implode(PHP_EOL, explode("|", "%")), PHP_EOL;' | xargs -I % php -r 'echo explode("#", "%")[1], PHP_EOL;' >> images-that-need-updating.list | |
fi | |
echo "Looking for newer upstream images" | |
php utils/newer-upstream-images.php >> images-that-need-updating.list | |
printf "image=%s" $(php utils/deduplicate-list.php) >> $GITHUB_OUTPUT | |
exit 0 | |
fi | |
echo "Not in a scheduled run, building all images" | |
printf "image=%s" $(cat all-images.list) >> $GITHUB_OUTPUT | |
exit 0 | |
env: | |
ALPINE: ${{ needs.supported-alpine-versions.outputs.alpine }} | |
DEBIAN: ${{ needs.supported-debian-versions.outputs.debian }} | |
PHP: ${{ needs.supported-php-versions.outputs.php }} | |
lint: | |
name: Linting Dockerfile-${{ matrix.type }} | |
runs-on: ubuntu-latest | |
needs: | |
- image-type-matrix | |
strategy: | |
fail-fast: false | |
matrix: | |
type: ${{ fromJson(needs.image-type-matrix.outputs.type) }} | |
steps: | |
- uses: actions/checkout@v2 | |
- name: Lint Dockerfile-${{ matrix.type }} | |
uses: docker://hadolint/hadolint:latest-debian | |
with: | |
entrypoint: hadolint | |
args: Dockerfile-${{ matrix.type }} | |
build: | |
name: Building "${{ matrix.image }}" on ${{ matrix.arch }} | |
needs: | |
- lint | |
- image-matrix | |
- supported-arch-matrix | |
- exclude-matrix | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
image: ${{ fromJson(needs.image-matrix.outputs.image) }} | |
arch: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }} | |
exclude: ${{ fromJson(needs.exclude-matrix.outputs.exclude) }} | |
steps: | |
- uses: actions/checkout@v2 | |
- uses: dbhi/qus/action@main | |
- run: mkdir ./docker-image/ | |
- uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: ./build-php.sh $(echo "${{ matrix.image }}" | tr '-' ' ') ${{ matrix.arch }} | |
- run: cat ./docker-image/image.tags | xargs -I % docker inspect --format='%={{.Id}}:{{index .Config.Env 7}}' % | |
- run: docker save "${DOCKER_IMAGE}" | gzip -9 > ./docker-image/image.tar | |
- run: docker images | |
- name: Upload Images | |
uses: actions/upload-artifact@v2 | |
with: | |
name: docker-image-${{ matrix.image }}-${{ matrix.arch }} | |
path: ./docker-image | |
scan-vulnerability: | |
name: Scanning "${{ matrix.image }}" for vulnerabilities on ${{ matrix.arch }} | |
needs: | |
- build | |
- image-matrix | |
- supported-arch-matrix | |
- exclude-matrix | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
image: ${{ fromJson(needs.image-matrix.outputs.image) }} | |
arch: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }} | |
exclude: ${{ fromJson(needs.exclude-matrix.outputs.exclude) }} | |
steps: | |
- uses: actions/checkout@v2 | |
if: contains(matrix.image, 'alpine') | |
- uses: dbhi/qus/action@main | |
if: contains(matrix.image, 'alpine') | |
- name: Download Images | |
if: contains(matrix.image, 'alpine') | |
uses: actions/download-artifact@v2 | |
with: | |
name: docker-image-${{ matrix.image }}-${{ matrix.arch }} | |
path: ./docker-image | |
- run: docker load --input ./docker-image/image.tar | |
if: contains(matrix.image, 'alpine') | |
- run: mkdir -p "./clair/${DOCKER_IMAGE}" | |
if: contains(matrix.image, 'alpine') | |
- run: make ci-scan-vulnerability | |
if: contains(matrix.image, 'alpine') | |
test: | |
name: Testing "${{ matrix.image }}" on ${{ matrix.arch }} | |
needs: | |
- build | |
- image-matrix | |
- supported-arch-matrix | |
- exclude-matrix | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
image: ${{ fromJson(needs.image-matrix.outputs.image) }} | |
arch: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }} | |
exclude: ${{ fromJson(needs.exclude-matrix.outputs.exclude) }} | |
steps: | |
- uses: actions/checkout@v2 | |
- uses: dbhi/qus/action@main | |
- name: Download Images | |
uses: actions/download-artifact@v2 | |
with: | |
name: docker-image-${{ matrix.image }}-${{ matrix.arch }} | |
path: ./docker-image | |
- run: ls -lasth ./docker-image | |
- run: docker load --input ./docker-image/image.tar | |
- run: IMAGE_BASE_VERSION=$(php -r 'echo explode("-", "${{ matrix.image }}")[2];') make $(php -r 'echo "test-", explode("-", str_replace(["zts-zts", "cli-nts"], ["zts", "nts"], "${{ matrix.image }}"))[0];') | |
env: | |
IMAGE_ARCH: ${{ matrix.arch }} | |
- run: rm -Rf ./docker-image/ | |
check-mark: | |
name: ✔️ | |
needs: | |
- lint | |
- build | |
- scan-vulnerability | |
- test | |
runs-on: ubuntu-latest | |
steps: | |
- run: echo "✔️" | |
push: | |
name: Pushing "${{ matrix.image }}" for ${{ matrix.arch }} | |
if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' | |
needs: | |
- check-mark | |
- image-matrix | |
- supported-arch-matrix | |
- exclude-matrix | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
image: ${{ fromJson(needs.image-matrix.outputs.image) }} | |
arch: ${{ fromJson(needs.supported-arch-matrix.outputs.arch) }} | |
exclude: ${{ fromJson(needs.exclude-matrix.outputs.exclude) }} | |
steps: | |
- uses: actions/checkout@v2 | |
- uses: dbhi/qus/action@main | |
- name: Download Images | |
uses: actions/download-artifact@v2 | |
with: | |
name: docker-image-${{ matrix.image }}-${{ matrix.arch }} | |
path: ./docker-image | |
- run: docker load --input ./docker-image/image.tar | |
- name: Login to container registries | |
uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: | | |
(jq -r 'to_entries | map("echo \"$" + .value + "\" | docker login " + .key + " --username \"${{ env.DOCKER_USER }}\" --password-stdin") | .[]' <<<"$DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING") | sh | |
env: | |
DOCKER_USER: ${{ secrets.HUB_USERNAME }} | |
GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} | |
HUB_PASSCODE: ${{ secrets.HUB_PASSCODE }} | |
- name: Retag | |
uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: | | |
(jq -r 'to_entries | map("cat ./docker-image/image.tags | xargs -I % docker tag % " + .key + "/%") | .[]' <<<"$DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING") | sh | |
- name: Push tags | |
uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: | | |
(jq -r 'to_entries | map("cat ./docker-image/image.tags | xargs -I % docker push " + .key + "/%") | .[]' <<<"$DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING") | sh | |
push-manifest: | |
name: Push ${{ matrix.image }} manifest | |
if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' | |
strategy: | |
fail-fast: false | |
matrix: | |
image: ${{ fromJson(needs.image-matrix.outputs.image) }} | |
needs: | |
- push | |
- image-matrix | |
- supported-arch-matrix | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v2 | |
- uses: dbhi/qus/action@main | |
- name: Download Images | |
uses: actions/download-artifact@v2 | |
with: | |
name: docker-image-${{ matrix.image }}-amd64 | |
path: ./docker-image | |
- name: Login to container registries | |
uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: | | |
(jq -r 'to_entries | map("echo \"$" + .value + "\" | docker login " + .key + " --username \"${{ env.DOCKER_USER }}\" --password-stdin") | .[]' <<<"$DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING") | sh | |
env: | |
DOCKER_USER: ${{ secrets.HUB_USERNAME }} | |
GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }} | |
HUB_PASSCODE: ${{ secrets.HUB_PASSCODE }} | |
- name: Docker info | |
run: docker info | |
- name: Push manifest to registries | |
uses: nick-invision/retry@v2 | |
with: | |
timeout_minutes: 120 | |
retry_wait_seconds: 30 | |
max_attempts: 5 | |
command: | | |
touch command.sh | |
(jq -r 'to_entries | map("cat ./docker-image/image.tags | xargs -I % php utils/create-manifest-command.php " + .key + " %") | .[]' <<<"$DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING") | sh | |
chmod +x command.sh | |
./command.sh | |
env: | |
TARGET_ARCHS: ${{ needs.supported-arch-matrix.outputs.arch }} |