From 47cc578b0b05851b3667b257882bf38f62c349b6 Mon Sep 17 00:00:00 2001 From: Pavlo Golub Date: Thu, 25 Sep 2025 16:10:29 +0200 Subject: [PATCH 1/3] [+] use a dedicated action for Docker builds --- .github/actions/build-docker/action.yml | 118 ++++++++++++++++++++++++ .github/workflows/build.yml | 32 ++++++- .github/workflows/docker.yml | 56 ----------- 3 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 .github/actions/build-docker/action.yml delete mode 100644 .github/workflows/docker.yml diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml new file mode 100644 index 00000000..be06d733 --- /dev/null +++ b/.github/actions/build-docker/action.yml @@ -0,0 +1,118 @@ +name: 'Build and Push Docker Images' +description: 'Builds multi-arch Docker images with caching and SemVer tagging using official Docker actions' + +inputs: + dockerfile: + description: 'Path to Dockerfile (relative to repository root)' + required: true + image-name: + description: 'Docker image name (without registry prefix)' + required: true + registry: + description: 'Docker registry (docker.io or ghcr.io)' + required: false + default: 'docker.io' + username: + description: 'Docker registry username' + required: true + password: + description: 'Docker registry password/token' + required: true + platforms: + description: 'Target platforms for multi-arch build' + required: false + default: 'linux/amd64,linux/arm64' + push: + description: 'Whether to push the image (true/false)' + required: false + default: 'false' + build-args: + description: 'Build arguments as KEY=VALUE pairs (one per line)' + required: false + default: '' + + cache-scope: + description: 'Cache scope for build cache' + required: false + default: 'default' + +outputs: + image-id: + description: 'Image ID of the built image' + value: ${{ steps.build.outputs.imageid }} + digest: + description: 'Image digest of the built image' + value: ${{ steps.build.outputs.digest }} + metadata: + description: 'Build result metadata' + value: ${{ steps.build.outputs.metadata }} + +runs: + using: 'composite' + steps: + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: all + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + network=host + + - name: Log in to Docker Registry + if: inputs.push == 'true' + uses: docker/login-action@v3 + with: + registry: ${{ inputs.registry == 'docker.io' && '' || inputs.registry }} + username: ${{ inputs.username }} + password: ${{ inputs.password }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.image-name }} + tags: | + # For releases: apply SemVer tags and latest (excludes pre-releases automatically) + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=semver,pattern=latest + # For branches: branch name as tag + type=ref,event=branch + # For PRs: pr- + type=ref,event=pr + # SHA for unique identification + type=sha,prefix=sha-,format=short + labels: | + org.opencontainers.image.title=${{ inputs.image-name }} + org.opencontainers.image.description=PgWatch - PostgreSQL monitoring solution + org.opencontainers.image.vendor=Cybertec PostgreSQL International GmbH + org.opencontainers.image.licenses=BSD-3-Clause + + - name: Build and push Docker image + id: build + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + push: ${{ inputs.push == 'true' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: ${{ inputs.build-args }} + cache-from: type=gha,scope=${{ inputs.cache-scope }} + cache-to: type=gha,mode=max,scope=${{ inputs.cache-scope }} + provenance: false + sbom: false + + - name: Output image details + shell: bash + run: | + echo "🐳 Built image: ${{ inputs.image-name }}" + echo "📋 Tags:" + echo "${{ steps.meta.outputs.tags }}" | sed 's/^/ - /' + echo "🔍 Digest: ${{ steps.build.outputs.digest }}" + echo "🆔 Image ID: ${{ steps.build.outputs.imageid }}" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b1f84446..a19b8669 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -197,4 +197,34 @@ jobs: echo "push_opt=--push" >> $GITHUB_ENV - name: Build mkdocs - run: mike deploy ${{ env.push_opt }} devel \ No newline at end of file + run: mike deploy ${{ env.push_opt }} devel + + test-docker-images: + if: true # false to skip job during debug + needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] + name: Test Docker Image Build + runs-on: ubuntu-latest + steps: + + - name: Check out code + uses: actions/checkout@v5 + + - name: Prepare build metadata + id: meta + run: | + echo "GIT_HASH=${{ github.sha }}" >> $GITHUB_OUTPUT + echo "GIT_TIME=$(git show -s --format=%cI HEAD)" >> $GITHUB_OUTPUT + echo "VERSION=${{ github.ref_name }}" >> $GITHUB_OUTPUT + + - name: Test build Docker image (fast, amd64 only) + uses: ./.github/actions/build-docker + with: + dockerfile: docker/Dockerfile + image-name: cybertecpostgresql/pg_timetable + platforms: linux/amd64 + push: 'false' + cache-scope: test-build + build-args: | + COMMIT=${{ steps.meta.outputs.GIT_HASH }} + DATE=${{ steps.meta.outputs.GIT_TIME }} + VERSION=${{ steps.meta.outputs.VERSION }} \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index b810307e..00000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Update Docker -on: - push: - paths: - - '**.go' - - '**.yaml' - - '**.yml' - - 'go.mod' - - 'go.sum' - - 'Dockerfile' - branches: - - 'master' - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - docker: - if: true # false to skip job during debug - runs-on: ubuntu-latest - steps: - - - name: Check out code - uses: actions/checkout@v5 - - - name: Set up Golang - uses: actions/setup-go@v6 - with: - go-version: '1.25' - - # despite the fact docker will build binary internally - # we want to stop workflow in case of any error before pushing to registry - - name: Get dependencies and Build - run: | - go version - go mod download - go build - - - name: Version strings - id: version - run: | - echo "RELEASE_TIME=$(git show -s --format=%cI HEAD)" >> $GITHUB_OUTPUT - - - name: Publish to Registry - uses: elgohr/Publish-Docker-Github-Action@v5 - env: - VERSION: ${{ github.ref_name }} - COMMIT: ${{ github.sha }} - DATE: ${{ steps.version.outputs.RELEASE_TIME }} - with: - name: cybertecpostgresql/pg_timetable - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - buildargs: VERSION,COMMIT,DATE From bb2529a5204c71f79a0935b85bf55130acd3c7ab Mon Sep 17 00:00:00 2001 From: Pavlo Golub Date: Thu, 25 Sep 2025 16:22:19 +0200 Subject: [PATCH 2/3] test --- .github/actions/build-docker/action.yml | 1 + .github/workflows/build.yml | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml index be06d733..787c5a47 100644 --- a/.github/actions/build-docker/action.yml +++ b/.github/actions/build-docker/action.yml @@ -107,6 +107,7 @@ runs: cache-to: type=gha,mode=max,scope=${{ inputs.cache-scope }} provenance: false sbom: false + load: true - name: Output image details shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a19b8669..b82ff796 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ concurrency: jobs: test-postgresql-windows: - if: true # false to skip job during debug + if: false # false to skip job during debug name: Test on Windows runs-on: windows-latest steps: @@ -55,7 +55,7 @@ jobs: test-postgresql-macos: - if: true # false to skip job during debug + if: false # false to skip job during debug name: Test on MacOS runs-on: macos-latest steps: @@ -103,7 +103,7 @@ jobs: run: go test -v -p 1 -parallel 1 -failfast ./... test-postgresql-ubuntu: - if: true # false to skip job during debug + if: false # false to skip job during debug name: Test and Build on Ubuntu runs-on: ubuntu-latest steps: @@ -155,7 +155,7 @@ jobs: args: release --snapshot --skip=publish --clean build-docs: - if: true # false to skip job during debug + if: false # false to skip job during debug needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] name: Build Docs runs-on: ubuntu-latest @@ -201,7 +201,7 @@ jobs: test-docker-images: if: true # false to skip job during debug - needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] + # needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] name: Test Docker Image Build runs-on: ubuntu-latest steps: @@ -219,7 +219,7 @@ jobs: - name: Test build Docker image (fast, amd64 only) uses: ./.github/actions/build-docker with: - dockerfile: docker/Dockerfile + dockerfile: Dockerfile image-name: cybertecpostgresql/pg_timetable platforms: linux/amd64 push: 'false' @@ -227,4 +227,8 @@ jobs: build-args: | COMMIT=${{ steps.meta.outputs.GIT_HASH }} DATE=${{ steps.meta.outputs.GIT_TIME }} - VERSION=${{ steps.meta.outputs.VERSION }} \ No newline at end of file + VERSION=${{ steps.meta.outputs.VERSION }} + + - name: Check image output + run: | + docker run --rm cybertecpostgresql/pg_timetable:pr-717 --version \ No newline at end of file From b052797b6e1e1ede96c2a6f9b99cffc4b37c0763 Mon Sep 17 00:00:00 2001 From: Pavlo Golub Date: Thu, 25 Sep 2025 16:56:50 +0200 Subject: [PATCH 3/3] update Release GHA workflow --- .github/actions/build-docker/action.yml | 1 - .github/workflows/build.yml | 14 ++++----- .github/workflows/release.yml | 38 +++++++++++++++++-------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/.github/actions/build-docker/action.yml b/.github/actions/build-docker/action.yml index 787c5a47..be06d733 100644 --- a/.github/actions/build-docker/action.yml +++ b/.github/actions/build-docker/action.yml @@ -107,7 +107,6 @@ runs: cache-to: type=gha,mode=max,scope=${{ inputs.cache-scope }} provenance: false sbom: false - load: true - name: Output image details shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b82ff796..cbb27523 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ concurrency: jobs: test-postgresql-windows: - if: false # false to skip job during debug + if: true # false to skip job during debug name: Test on Windows runs-on: windows-latest steps: @@ -55,7 +55,7 @@ jobs: test-postgresql-macos: - if: false # false to skip job during debug + if: true # false to skip job during debug name: Test on MacOS runs-on: macos-latest steps: @@ -103,7 +103,7 @@ jobs: run: go test -v -p 1 -parallel 1 -failfast ./... test-postgresql-ubuntu: - if: false # false to skip job during debug + if: true # false to skip job during debug name: Test and Build on Ubuntu runs-on: ubuntu-latest steps: @@ -155,7 +155,7 @@ jobs: args: release --snapshot --skip=publish --clean build-docs: - if: false # false to skip job during debug + if: true # false to skip job during debug needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] name: Build Docs runs-on: ubuntu-latest @@ -201,7 +201,7 @@ jobs: test-docker-images: if: true # false to skip job during debug - # needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] + needs: [test-postgresql-ubuntu, test-postgresql-windows, test-postgresql-macos] name: Test Docker Image Build runs-on: ubuntu-latest steps: @@ -228,7 +228,3 @@ jobs: COMMIT=${{ steps.meta.outputs.GIT_HASH }} DATE=${{ steps.meta.outputs.GIT_TIME }} VERSION=${{ steps.meta.outputs.VERSION }} - - - name: Check image output - run: | - docker run --rm cybertecpostgresql/pg_timetable:pr-717 --version \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d3682272..5030b36e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,13 @@ name: Release + +permissions: + contents: write + packages: write + pages: write + deployments: write + pull-requests: write + issues: write + on: release: types: [created] @@ -38,20 +47,25 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v5 - - name: Version strings - id: version + - name: Prepare build metadata + id: meta run: | - echo "RELEASE_TIME=$(git show -s --format=%cI HEAD)" >> $GITHUB_OUTPUT + echo "GIT_HASH=${{ github.sha }}" >> $GITHUB_OUTPUT + echo "GIT_TIME=$(git show -s --format=%cI HEAD)" >> $GITHUB_OUTPUT + echo "VERSION=${{ github.ref_name }}" >> $GITHUB_OUTPUT - - name: Publish to Registry - uses: elgohr/Publish-Docker-Github-Action@v5 - env: - VERSION: ${{ github.ref_name }} - COMMIT: ${{ github.sha }} - DATE: ${{ steps.version.outputs.RELEASE_TIME }} + - name: Build and push Docker image + uses: ./.github/actions/build-docker with: - name: cybertecpostgresql/pg_timetable + dockerfile: Dockerfile + image-name: cybertecpostgresql/pg_timetable + registry: docker.io username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - buildargs: VERSION,COMMIT,DATE - tag_semver: true \ No newline at end of file + platforms: linux/amd64,linux/arm64 + push: 'true' + cache-scope: shared-release + build-args: | + COMMIT=${{ steps.meta.outputs.GIT_HASH }} + DATE=${{ steps.meta.outputs.GIT_TIME }} + VERSION=${{ steps.meta.outputs.VERSION }}