diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml new file mode 100644 index 0000000..12d050a --- /dev/null +++ b/.github/workflows/build-image.yml @@ -0,0 +1,143 @@ +name: Push image +on: + workflow_call: + inputs: + containerfile: + description: Which containerfile/dockerfile to build + required: true + type: string + image: + description: image name + required: true + type: string + tag: + description: image tag + required: true + type: string + update-check: + description: command to run on old image and check for updates + required: true + type: string + +jobs: + detect-changes: + runs-on: ubuntu-latest + outputs: + detected: ${{ steps.result.outputs.detected }} + steps: + - uses: actions/checkout@v4 + + - name: Pull latest image + run: | + latest_tag="docker.pkg.github.com/${{ inputs.image }}/${{ inputs.tag }}" + echo "latest_tag=$latest_tag" >> "$GITHUB_ENV" + + echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com \ + -u ${{ github.actor }} --password-stdin + docker pull "$latest_tag" + docker logout docker.pkg.github.com + + - name: Check if git revision has changed + id: revision + run: | + revision="$(docker image inspect --format \ + '{{index .Config.Labels "org.opencontainers.image.revision"}}' \ + "$latest_tag")" + echo "$revision" + if [ "$revision" != "$GITHUB_SHA" ]; then + echo "Latest image revision ($revision) is not the same as current revision ($GITHUB_SHA)" + echo "changed_revision=true" >> result + else + echo "Latest image revision is the same as current revision ($GITHUB_SHA)" + echo "changed_revision=false" >> result + fi + + - name: Check for new updates + id: updates + run: | + packages="$(docker run --rm --entrypoint=/bin/sh "$latest_tag" -c "${{ inputs.update-check }}")" + echo "$packages" + if [ "${#packages}" -gt 0 ]; then + echo "Updates available" + echo "new_updates=true" >> result + else + echo "No new updates" + echo "new_updates=false" >> result + fi + + - name: Results + id: result + run: | + cat result + if grep -q "=true" result; then + echo "Result: changes detected" + echo "detected=true" >> "$GITHUB_OUTPUT" + else + echo "Result: no change detected" + echo "detected=false" >> "$GITHUB_OUTPUT" + fi + + build: + runs-on: ubuntu-latest + needs: detect-changes + if: needs.detect-changes.outputs.detected == 'true' + steps: + - uses: actions/checkout@v4 + with: + submodules: true # for shunit2 + + - name: Build image + run: | + docker build . \ + --pull=true \ + --file="${{ inputs.containerfile }}" \ + --tag="${{ inputs.image }}:${{ inputs.tag }}" \ + --label="org.opencontainers.image.source=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" \ + --label="org.opencontainers.image.revision=$GITHUB_SHA" \ + --label="org.opencontainers.image.created=$(date --rfc-3339=seconds)" + + - name: Test image + run: tests/run "${{ inputs.image }}:${{ inputs.tag }}" + + - name: Save image + run: docker save -o "${{ inputs.tag }}.tar" "${{ inputs.image }}:${{ inputs.tag }}" + + - name: Upload image as artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.tag }} + path: "${{ inputs.tag }}.tar" + retention-days: 1 + + push: + runs-on: ubuntu-latest + needs: build + if: github.ref == 'refs/heads/master' + steps: + - uses: actions/checkout@v4 + + - name: Download image + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.tag }} + + - name: Load image + run: docker load -i "${{ inputs.tag }}.tar" + + - name: Push image to GitHub registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com \ + -u ${{ github.actor }} --password-stdin + + github_tag=docker.pkg.github.com/${{ inputs.image }}/${{ inputs.tag }} + docker tag "${{ inputs.image }}:${{ inputs.tag }}" $github_tag + docker push "$github_tag" + docker logout docker.pkg.github.com + + - name: Push images to Docker Hub registry + run: | + echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login \ + -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin + + docker push "${{ inputs.image }}:${{ inputs.tag }}" + docker logout diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cafe916..9d90bde 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,78 +9,43 @@ on: - "*.txt" - "*.png" pull_request: - -env: - IMAGE_NAME: atmoz/sftp + workflow_dispatch: jobs: - build: + verify: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 # for proper signature verification - submodules: true # for shunit2 + + - name: Verify signature + if: github.repository == 'atmoz/sftp' + uses: atmoz/git-verify-ref@master + with: + import-github-users: atmoz - name: Run ShellCheck uses: ludeeus/action-shellcheck@master with: ignore_paths: tests/shunit2 - - name: Build debian image - run: | - docker build . \ - --pull=true \ - --file=Dockerfile \ - --tag="$IMAGE_NAME:latest" \ - --tag="$IMAGE_NAME:debian" \ - --label="org.opencontainers.image.source=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" \ - --label="org.opencontainers.image.revision=$GITHUB_SHA" \ - --label="org.opencontainers.image.created=$(date --rfc-3339=seconds)" - - - name: Test debian image - run: tests/run $IMAGE_NAME:debian - - - name: Build alpine image - run: | - docker build . \ - --pull=true \ - --file=Dockerfile-alpine \ - --tag="$IMAGE_NAME:alpine" \ - --label="org.opencontainers.image.source=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" \ - --label="org.opencontainers.image.revision=$GITHUB_SHA" \ - --label="org.opencontainers.image.created=$(date --rfc-3339=seconds)" - - - name: Test alpine image - run: tests/run $IMAGE_NAME:alpine - - - name: Verify signature - if: github.ref == 'refs/heads/master' - uses: atmoz/git-verify-ref@master - with: - import-github-users: atmoz - - - name: Push images to Docker Hub registry - if: github.ref == 'refs/heads/master' - run: | - echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login \ - -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin - - docker push --all-tags $IMAGE_NAME - docker logout - - - name: Push images to GitHub registry - if: github.ref == 'refs/heads/master' - run: | - echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com \ - -u ${{ github.actor }} --password-stdin - - TAG_DEBIAN=docker.pkg.github.com/$GITHUB_REPOSITORY/debian - TAG_ALPINE=docker.pkg.github.com/$GITHUB_REPOSITORY/alpine - docker tag $IMAGE_NAME:debian $TAG_DEBIAN - docker tag $IMAGE_NAME:alpine $TAG_ALPINE - docker push $TAG_DEBIAN - docker push $TAG_ALPINE - docker logout docker.pkg.github.com + alpine: + needs: verify + uses: ./.github/workflows/build-image.yml + with: + containerfile: Dockerfile-alpine + image: "$GITHUB_REPOSITORY" + tag: alpine + update-check: "apk update &>/dev/null && apk version -q -l '>'" + secrets: inherit + debian: + needs: verify + uses: ./.github/workflows/build-image.yml + with: + containerfile: Dockerfile + image: "$GITHUB_REPOSITORY" + tag: debian + update-check: "apt-get update &>/dev/null && apt-get upgrade -s | grep '^Inst' || true" + secrets: inherit