From 0984b63cf87d6a73433f0dd4bcaebf2f5a36846b Mon Sep 17 00:00:00 2001 From: JargeZ Date: Sun, 14 Jun 2026 21:37:25 +1000 Subject: [PATCH 1/3] Multiarch Remove local push task --- .github/workflows/docker-image.yml | 49 +++++++++++++++++++++--------- Taskfile.yml | 10 ++++++ 2 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 Taskfile.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index c481f6d..fc4ee7f 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -2,24 +2,43 @@ name: Docker Image CI on: push: - branches: [ master ] + branches: [ master, multiarch ] jobs: - build: - runs-on: ubuntu-latest + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} steps: - - uses: actions/checkout@v2 - - name: Get the version - id: vars - run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" - - name: Build the Docker image - run: docker build . --file Dockerfile --tag backuptools/postgres-backup-s3:${{steps.vars.outputs.sha_short}} --tag backuptools/postgres-backup-s3 - - name: Login to Dockerhub - run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin - - name: Push the Docker image - run: docker push backuptools/postgres-backup-s3:${{steps.vars.outputs.sha_short}} - - name: Push the :latest Docker image - run: docker push backuptools/postgres-backup-s3 + - uses: actions/checkout@v4 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + images: backuptools/postgres-backup-s3 + tags: | + type=raw,value=latest + type=sha,prefix=,format=short + + - name: Login to Docker Hub + if: env.DOCKERHUB_USERNAME != '' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_PASSWORD }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: ${{ env.DOCKERHUB_USERNAME != '' }} + tags: ${{ steps.meta.outputs.tags }} diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..8df7b04 --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,10 @@ +version: '3' + +vars: + IMAGE: backuptools/postgres-backup-s3 + +tasks: + build: + desc: "Build linux/amd64+linux/arm64 locally (no push)" + cmds: + - docker buildx build --platform linux/amd64,linux/arm64 --progress=plain . From 53d302805065f012a2d67037af06be6481f63bf7 Mon Sep 17 00:00:00 2001 From: JargeZ Date: Sun, 14 Jun 2026 21:58:13 +1000 Subject: [PATCH 2/3] Finish test Verify data in test Test job ci --- .github/workflows/docker-image.yml | 12 +++ Taskfile.yml | 29 +++++++ docker-compose.test.yml | 15 +++- docker-compose.yml | 2 - test-init.sql | 121 +++++++++++++++++++++++++++++ 5 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 test-init.sql diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index fc4ee7f..e80b7c5 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -5,7 +5,19 @@ on: branches: [ master, multiarch ] jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Task + uses: arduino/setup-task@v2 + + - name: Run integration tests + run: task test + build: + needs: test runs-on: ubuntu-latest env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} diff --git a/Taskfile.yml b/Taskfile.yml index 8df7b04..96b4fd8 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -8,3 +8,32 @@ tasks: desc: "Build linux/amd64+linux/arm64 locally (no push)" cmds: - docker buildx build --platform linux/amd64,linux/arm64 --progress=plain . + + test: + desc: "Integration test: build, run backup against postgres+minio, assert success" + cmds: + - defer: docker compose -f docker-compose.test.yml down -v + - docker compose -f docker-compose.test.yml up -d --build --wait postgres minio + - | + OUTPUT=$(docker compose -f docker-compose.test.yml run --rm --no-deps postgres-backup /entrypoint.sh 2>&1) + echo "$OUTPUT" + echo "$OUTPUT" | grep -q "Postgres backup completed successfully" \ + || (echo "FAIL: success message not found in output" && exit 1) + - | + FILES=$(docker compose -f docker-compose.test.yml run --rm --no-deps \ + -e MC_HOST_backup=http://minio:minio123@minio:9000 \ + postgres-backup mc ls backup/test-backup/ --recursive --insecure 2>/dev/null) + echo "$FILES" + echo "$FILES" | grep -q "\.pgdump" \ + || (echo "FAIL: no .pgdump files found in minio bucket" && exit 1) + echo "PASS: backup file verified in minio" + - | + if docker compose -f docker-compose.test.yml run --rm --no-deps \ + -e MC_HOST_backup=http://minio:minio123@minio:9000 \ + postgres-backup sh -c \ + 'mc find backup/test-backup/ --insecure 2>/dev/null | head -1 | xargs mc cat --insecure | pigz -d | grep -q "test_table"'; then + echo "PASS: backup content verified (test_table found in dump)" + else + echo "FAIL: test_table not found in backup content" + exit 1 + fi diff --git a/docker-compose.test.yml b/docker-compose.test.yml index d247b97..0864a9b 100644 --- a/docker-compose.test.yml +++ b/docker-compose.test.yml @@ -1,5 +1,3 @@ -version: "3.9" - volumes: minio_data: postgres_data: @@ -31,6 +29,12 @@ services: MINIO_ROOT_USER: minio MINIO_ROOT_PASSWORD: minio123 command: server /data --console-address ":9001" --address 0.0.0.0:9000 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 2s + timeout: 5s + retries: 15 + start_period: 3s postgres: image: postgres:15-alpine @@ -42,4 +46,9 @@ services: - postgres_data:/var/lib/postgresql/data - ./test-init.sql:/docker-entrypoint-initdb.d/init-dump.sql ports: - - "5434:5432" \ No newline at end of file + - "5434:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 2s + timeout: 5s + retries: 15 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 75c756a..ee17fea 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: "3" - services: postgres-backup: image: backuptools/postgres-backup-s3 diff --git a/test-init.sql b/test-init.sql new file mode 100644 index 0000000..d45729f --- /dev/null +++ b/test-init.sql @@ -0,0 +1,121 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 15.5 +-- Dumped by pg_dump version 16.2 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +\connect postgres + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: DATABASE postgres; Type: COMMENT; Schema: -; Owner: postgres +-- + +COMMENT ON DATABASE postgres IS 'default administrative connection database'; + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: test_table; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.test_table ( + id integer NOT NULL, + login text NOT NULL +); + + +ALTER TABLE public.test_table OWNER TO postgres; + +-- +-- Name: test_table_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres +-- + +CREATE SEQUENCE public.test_table_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +ALTER SEQUENCE public.test_table_id_seq OWNER TO postgres; + +-- +-- Name: test_table_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres +-- + +ALTER SEQUENCE public.test_table_id_seq OWNED BY public.test_table.id; + + +-- +-- Name: test_table id; Type: DEFAULT; Schema: public; Owner: postgres +-- + +ALTER TABLE ONLY public.test_table ALTER COLUMN id SET DEFAULT nextval('public.test_table_id_seq'::regclass); + + +-- +-- Data for Name: test_table; Type: TABLE DATA; Schema: public; Owner: postgres +-- + +COPY public.test_table (id, login) FROM stdin; +1 asd +2 qwe +3 zxc +4 ert +5 dfg +\. + + +-- +-- Name: test_table_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres +-- + +SELECT pg_catalog.setval('public.test_table_id_seq', 5, true); + + +-- +-- Name: test_table_id_uindex; Type: INDEX; Schema: public; Owner: postgres +-- + +CREATE UNIQUE INDEX test_table_id_uindex ON public.test_table USING btree (id); + + +-- +-- Name: test_table_login_uindex; Type: INDEX; Schema: public; Owner: postgres +-- + +CREATE UNIQUE INDEX test_table_login_uindex ON public.test_table USING btree (login); + + +-- +-- PostgreSQL database dump complete +-- + From 289bcff720e534e44cb9b04d65cf970bf4014e2d Mon Sep 17 00:00:00 2001 From: JargeZ Date: Sun, 14 Jun 2026 22:11:16 +1000 Subject: [PATCH 3/3] Job triggers --- .github/workflows/docker-image.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e80b7c5..b613369 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -2,7 +2,9 @@ name: Docker Image CI on: push: - branches: [ master, multiarch ] + branches: [ master ] + pull_request: + branches: [ master ] jobs: test: @@ -17,8 +19,8 @@ jobs: run: task test build: - needs: test runs-on: ubuntu-latest + needs: test env: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} @@ -35,7 +37,7 @@ jobs: type=sha,prefix=,format=short - name: Login to Docker Hub - if: env.DOCKERHUB_USERNAME != '' + if: github.event_name == 'push' && env.DOCKERHUB_USERNAME != '' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} @@ -52,5 +54,5 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 - push: ${{ env.DOCKERHUB_USERNAME != '' }} + push: ${{ github.event_name == 'push' && env.DOCKERHUB_USERNAME != '' }} tags: ${{ steps.meta.outputs.tags }}