diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7960d3b..c4fdf3f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,140 +63,180 @@ jobs: entrypoint: hadolint args: ./images/${{ matrix.image }}/Dockerfile build-docker-image: - name: Build ${{ matrix.image }} Docker + name: Build ${{ matrix.image }} Docker (${{ matrix.platform }}) strategy: fail-fast: false matrix: + platform: + - linux/amd64 + - linux/arm64 image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} needs: - generate-image-strategy - lint-dockerfile runs-on: ubuntu-latest steps: + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY_IMAGE }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: network=host - uses: actions/checkout@v4 - run: cp -R $(echo -e "./images/$(ls ./images/ | shuf -n 1)") ./images/random if: matrix.image == 'random' - - run: docker image build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` -t "${DOCKER_IMAGE}:${{ matrix.image }}" --no-cache --build-arg VERSION=$TAG_VERSION ./images/${{ matrix.image }}/ - run: mkdir ./docker-image - - run: docker save "${DOCKER_IMAGE}:${{ matrix.image }}" -o ./docker-image/docker_image.tar - - uses: actions/upload-artifact@master + - run: docker image build --build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` --build-arg VCS_REF=`git rev-parse --short HEAD` -t "${DOCKER_IMAGE}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" --no-cache --build-arg VERSION=$TAG_VERSION ./images/${{ matrix.image }}/ + - run: docker save "${DOCKER_IMAGE}:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" -o ./docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar +# - name: Build +# uses: docker/build-push-action@v6 +# with: +# context: ./images/${{ matrix.image }}/ +# tags: ${{ env.DOCKER_IMAGE }}:${{ matrix.image }} +# platforms: ${{ matrix.platform }} +# labels: ${{ steps.meta.outputs.labels }} +# outputs: type=tar,dest=./docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar +# cache-from: type=gha +# cache-to: type=gha,mode=max + - uses: actions/upload-artifact@v4 with: - name: docker-image-${{ matrix.image }} + name: docker-image-${{ matrix.image }}-${{ env.PLATFORM_PAIR }} path: ./docker-image scan-vulnerability: - name: Scan ${{ matrix.image }} for vulnerabilities + name: Scan ${{ matrix.image }} for vulnerabilities (${{ matrix.platform }}) strategy: fail-fast: false matrix: + platform: + - linux/amd64 + - linux/arm64 image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} needs: - generate-image-strategy - build-docker-image runs-on: ubuntu-latest steps: + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 - uses: actions/checkout@v4 - - uses: actions/download-artifact@master - with: - name: docker-image-${{ matrix.image }} - path: ./docker-image - - run: docker load --input ./docker-image/docker_image.tar - - run: rm -Rf ./docker-image/ - - run: echo -e "${DOCKER_IMAGE}:${{ matrix.image }}" | 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 --format table %' - tests: - name: Test ${{ matrix.image }} against ${{ matrix.rule }} - needs: - - generate-image-strategy - - generate-rule-strategy - - scan-vulnerability - strategy: - fail-fast: false - matrix: - image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} - rule: ${{ fromJson(needs.generate-rule-strategy.outputs.rules) }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@master + - uses: actions/download-artifact@v4 with: - name: docker-image-${{ matrix.image }} - path: ./docker-image - - run: docker load --input ./docker-image/docker_image.tar - - name: Start image ${{ matrix.image }} - run: docker run -d --rm -v ${GITHUB_WORKSPACE}/${REDIRECT_CONFIG_FILE}:/etc/redirect/config.yaml ${DOCKER_IMAGE}:${{ matrix.image }} - env: - IMAGE: ${{ steps.build.outputs.tag }} - REDIRECT_CONFIG_FILE: tests/rules/${{ matrix.rule }}/config.yaml - - name: Get running image ID - id: ps - run: printf "::set-output name=id::%s" $(docker ps --format "{{.ID}}") - env: - IMAGE: ${{ steps.build.outputs.tag }} - - name: Get running image IP - id: inspect - run: printf "::set-output name=ip::%s" $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${IMAGE_ID}) - env: - IMAGE_ID: ${{ steps.ps.outputs.id }} - - name: Sleep 13 seconds before attempting to connect - run: sleep 13 - - name: Test that redirect port is reachable - run: curl http://${IMAGE_IP}:7132/ - env: - IMAGE_IP: ${{ steps.inspect.outputs.ip }} - - name: Test that metrics port is reachable - run: curl http://${IMAGE_IP}:7133/ - env: - IMAGE_IP: ${{ steps.inspect.outputs.ip }} - - name: Run unit tests ${{ matrix.rule }} against ${{ matrix.image }} - run: docker run -i loadimpact/k6 run -u 1000 -d 30s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE} - env: - IMAGE: ${{ matrix.image }} - IMAGE_IP: ${{ steps.inspect.outputs.ip }} - IMAGE_ID: ${{ steps.ps.outputs.id }} - SCRIPT_FILEIMAGE: ./tests/rules/${{ matrix.rule }}/unit.js - - name: Run metrics tests ${{ matrix.rule }} against ${{ matrix.image }} - run: docker run -i loadimpact/k6 run -u 10 -d 10s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE} - env: - IMAGE: ${{ matrix.image }} - IMAGE_IP: ${{ steps.inspect.outputs.ip }} - IMAGE_ID: ${{ steps.ps.outputs.id }} - SCRIPT_FILEIMAGE: ./tests/rules/${{ matrix.rule }}/metrics.js - - name: Docker logs for image ${{ matrix.image }} - run: docker logs ${IMAGE_ID} - env: - IMAGE_ID: ${{ steps.ps.outputs.id }} - push-image: - if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' - name: Push ${{ matrix.image }} to ${{ matrix.registry }} - strategy: - fail-fast: false - matrix: - registry: ${{ fromJson(needs.registry-matrix.outputs.registry) }} - image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} - needs: - - generate-image-strategy - - tests - - registry-matrix - runs-on: ubuntu-latest - steps: - - uses: actions/download-artifact@master - with: - name: docker-image-${{ matrix.image }} - path: ./docker-image - - run: docker load --input ./docker-image/docker_image.tar - - run: rm -Rf ./docker-image/ - - name: Login to ${{ matrix.registry }} - run: | - echo "${{ env.DOCKER_PASSWORD }}" | \ - docker login ${{ matrix.registry }} \ - --username "${{ env.DOCKER_USER }}" \ - --password-stdin - env: - DOCKER_USER: ${{ secrets.HUB_USERNAME }} - DOCKER_PASSWORD: ${{ secrets[fromJson(env.DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING)[matrix.registry]] }} - - name: Docker info - run: docker info - - run: docker tag ${DOCKER_IMAGE}:${{ matrix.image }} ${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }} - - name: Echo full tag - run: echo -e "${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }}" - - name: Push image to Docker Hub - run: docker push "${{ matrix.registry }}/${DOCKER_IMAGE}:${{ matrix.image }}" + name: docker-image-${{ matrix.image }}-${{ env.PLATFORM_PAIR }} + path: /tmp/docker-image + - run: docker load --input /tmp/docker-image/docker_image-${{ env.PLATFORM_PAIR }}.tar + - run: rm -Rf /tmp/docker-image/ + - run: echo -e "wyrihaximusnet/redirect:${{ matrix.image }}-${{ env.PLATFORM_PAIR }}" | 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 --format table %' +# tests: +# name: Test ${{ matrix.image }} against ${{ matrix.rule }} +# needs: +# - generate-image-strategy +# - generate-rule-strategy +# - scan-vulnerability +# strategy: +# fail-fast: false +# matrix: +# image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} +# rule: ${{ fromJson(needs.generate-rule-strategy.outputs.rules) }} +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v4 +# - uses: actions/download-artifact@v4 +# with: +# name: docker-image-${{ matrix.image }} +# path: /tmp/docker-image +# - run: docker load --input /tmp/docker-image/docker_image.tar +# - run: docker image ls -a +# - run: docker manifest inspect $(echo "wyrihaximusnet/redirect:${{ matrix.image }}" | tr '[:upper:]' '[:lower:]') +# - run: docker manifest inspect $(echo "wyrihaximusnet/redirect:${{ matrix.image }}" | tr '[:upper:]' '[:lower:]') | docker run --rm -i backplane/jq '([.manifests[].platform | select(.os != "unknown")]?) | .[] | (.os + "/" + .architecture)' | docker run --rm -i backplane/jq -s '. | join(",")' +# - name: Start image ${{ matrix.image }} +# run: docker run -d --rm -v ${GITHUB_WORKSPACE}/${REDIRECT_CONFIG_FILE}:/etc/redirect/config.yaml wyrihaximusnet/redirect:${{ matrix.image }} +# env: +# IMAGE: ${{ steps.build.outputs.tag }} +# REDIRECT_CONFIG_FILE: tests/rules/${{ matrix.rule }}/config.yaml +# - name: Get running image ID +# id: ps +# run: printf "::set-output name=id::%s" $(docker ps --format "{{.ID}}") +# env: +# IMAGE: ${{ steps.build.outputs.tag }} +# - name: Get running image IP +# id: inspect +# run: printf "::set-output name=ip::%s" $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${IMAGE_ID}) +# env: +# IMAGE_ID: ${{ steps.ps.outputs.id }} +# - name: Sleep 13 seconds before attempting to connect +# run: sleep 13 +# - name: Test that redirect port is reachable +# run: curl http://${IMAGE_IP}:7132/ +# env: +# IMAGE_IP: ${{ steps.inspect.outputs.ip }} +# - name: Test that metrics port is reachable +# run: curl http://${IMAGE_IP}:7133/ +# env: +# IMAGE_IP: ${{ steps.inspect.outputs.ip }} +# - name: Run unit tests ${{ matrix.rule }} against ${{ matrix.image }} +# run: docker run -i loadimpact/k6 run -u 1000 -d 30s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE} +# env: +# IMAGE: ${{ matrix.image }} +# IMAGE_IP: ${{ steps.inspect.outputs.ip }} +# IMAGE_ID: ${{ steps.ps.outputs.id }} +# SCRIPT_FILEIMAGE: ./tests/rules/${{ matrix.rule }}/unit.js +# - name: Run metrics tests ${{ matrix.rule }} against ${{ matrix.image }} +# run: docker run -i loadimpact/k6 run -u 10 -d 10s -e IMAGE_IP=${IMAGE_IP} -< ${SCRIPT_FILEIMAGE} +# env: +# IMAGE: ${{ matrix.image }} +# IMAGE_IP: ${{ steps.inspect.outputs.ip }} +# IMAGE_ID: ${{ steps.ps.outputs.id }} +# SCRIPT_FILEIMAGE: ./tests/rules/${{ matrix.rule }}/metrics.js +# - name: Docker logs for image ${{ matrix.image }} +# run: docker logs ${IMAGE_ID} +# env: +# IMAGE_ID: ${{ steps.ps.outputs.id }} +# push-image: +# if: (github.event_name == 'push' || github.event_name == 'schedule') && github.ref == 'refs/heads/master' +# name: Push ${{ matrix.image }} to ${{ matrix.registry }} +# strategy: +# fail-fast: false +# matrix: +# registry: ${{ fromJson(needs.registry-matrix.outputs.registry) }} +# image: ${{ fromJson(needs.generate-image-strategy.outputs.images) }} +# needs: +# - generate-image-strategy +# - tests +# - registry-matrix +# runs-on: ubuntu-latest +# steps: +# - uses: actions/download-artifact@v4 +# with: +# name: docker-image-${{ matrix.image }} +# path: /tmp/docker-image +# - run: docker load --input /tmp/docker-image/docker_image.tar +# - run: rm -Rf /tmp/docker-image/ +# - name: Login to ${{ matrix.registry }} +# run: | +# echo "${{ env.DOCKER_PASSWORD }}" | \ +# docker login ${{ matrix.registry }} \ +# --username "${{ env.DOCKER_USER }}" \ +# --password-stdin +# env: +# DOCKER_USER: ${{ secrets.HUB_USERNAME }} +# DOCKER_PASSWORD: ${{ secrets[fromJson(env.DOCKER_IMAGE_REGISTRIES_SECRET_MAPPING)[matrix.registry]] }} +# - name: Docker info +# run: docker info +# - run: docker tag wyrihaximusnet/redirect:${{ matrix.image }} ${{ matrix.registry }}/wyrihaximusnet/redirect:${{ matrix.image }} +# - name: Echo full tag +# run: echo -e "${{ matrix.registry }}/wyrihaximusnet/redirect:${{ matrix.image }}" +# - name: Push image to Docker Hub +# run: docker push "${{ matrix.registry }}/wyrihaximusnet/redirect:${{ matrix.image }}"