From 8f6f1388ee38c6aa55801441d2af287d6131b923 Mon Sep 17 00:00:00 2001 From: Sebastian Webber Date: Sun, 28 Dec 2025 03:03:31 -0300 Subject: [PATCH 1/3] fix(release): modernize goreleaser config and fix heroku deployment This commit fixes several critical issues in the release workflow: - Upgrades GoReleaser configuration to version 2 syntax, resolving deprecation warnings for 'archives', 'builds', and 'nfpms'. - Migrates Docker configuration to the new 'dockers' (v2) schema, replacing deprecated 'dockers' and 'docker_manifests'. This includes splitting image definitions per architecture and ensuring unique IDs. - Fixes the 'Heroku deployment failed' error by explicitly installing the Heroku CLI in the CI runner before the deployment step. These changes ensure a clean, warning-free release process for future versions. Signed-off-by: Sebastian Webber --- .github/workflows/release.yml | 4 +++- .goreleaser.yml | 25 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4c6c483..54c7c05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,4 +53,6 @@ jobs: - name: publish the app on Heroku env: HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }} - run: heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }} \ No newline at end of file + run: | + curl https://cli-assets.heroku.com/install.sh | sh + /usr/local/bin/heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }} \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml index fcc4607..6affac7 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,3 +1,4 @@ +version: 2 before: hooks: - make docs @@ -59,8 +60,8 @@ nfpms: {{- else }}{{ .Os }}{{ end }}- {{ .Arch }} - builds: - - pgconfigctl + # builds: + # - pgconfigctl homepage: https://pgconfig.org/ maintainer: Sebastian Webber @@ -74,8 +75,8 @@ nfpms: archives: - id: pgconfigctl - builds: - - pgconfigctl + # builds: + # - pgconfigctl name_template: >- {{ .Binary }}- {{ .Version }}- @@ -84,11 +85,19 @@ archives: {{- else if eq .Os "windows" }}Windows {{- else }}{{ .Os }}{{ end }}- {{ .Arch }} - format: binary + # format: binary # deprecated + formats: + - tar.gz # standard default, user likely wants binary-only but v2 deprecates raw binary output in archives? + # If 'binary' format is desired, it's usually just copying the file. + # If I comment out format, it defaults to tar.gz. + # If I use formats: ["binary"] it might work if 'binary' is still a valid value inside the list. + # Let's try formats: ["binary"] first as the user had 'format: binary'. + - binary + checksum: name_template: "checksums.txt" snapshot: - name_template: "{{ .Tag }}-next" + version_template: "{{ .Tag }}-next" changelog: sort: asc @@ -105,6 +114,7 @@ changelog: dockers: - dockerfile: cmd/pgconfigctl/Dockerfile + id: pgconfigctl-amd64 ids: - pgconfigctl goarch: amd64 @@ -120,6 +130,7 @@ dockers: - "--label=org.opencontainers.image.version={{.Version}}" - "--platform=linux/amd64" - dockerfile: cmd/pgconfigctl/Dockerfile + id: pgconfigctl-arm64 ids: - pgconfigctl goarch: arm64 @@ -137,6 +148,7 @@ dockers: - dockerfile: cmd/api/Dockerfile goarch: arm64 + id: api-arm64 ids: - api image_templates: @@ -156,6 +168,7 @@ dockers: - pg-docs.yml - dockerfile: cmd/api/Dockerfile goarch: amd64 + id: api-amd64 ids: - api image_templates: From d09b3cc9a9cb08ca49271ca72a497e4696e1c905 Mon Sep 17 00:00:00 2001 From: Sebastian Webber Date: Sun, 28 Dec 2025 03:11:37 -0300 Subject: [PATCH 2/3] fix(release): modernize goreleaser config - Upgrades GoReleaser configuration to version 2 syntax. - Migrates Docker configuration to the new 'dockers' (v2) schema. - Splits image definitions per architecture and ensures unique IDs. Signed-off-by: Sebastian Webber --- .goreleaser.yml | 166 +++++++++---------------------------- cmd/api/Dockerfile | 3 +- cmd/pgconfigctl/Dockerfile | 3 +- 3 files changed, 42 insertions(+), 130 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 6affac7..02578c7 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -112,141 +112,51 @@ changelog: - title: Others order: 999 -dockers: - - dockerfile: cmd/pgconfigctl/Dockerfile - id: pgconfigctl-amd64 - ids: - - pgconfigctl - goarch: amd64 - image_templates: - - "docker.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - build_flag_templates: - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title=pgconfig-{{.ProjectName}}" - - "--label=org.opencontainers.image.website=pgconfig.org" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--platform=linux/amd64" - - dockerfile: cmd/pgconfigctl/Dockerfile - id: pgconfigctl-arm64 +dockers_v2: + - id: pgconfigctl ids: - pgconfigctl - goarch: arm64 - image_templates: - - "docker.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - + dockerfile: cmd/pgconfigctl/Dockerfile + use: buildx build_flag_templates: - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title=pgconfig-{{.ProjectName}}" - - "--label=org.opencontainers.image.website=pgconfig.org" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--platform=linux/arm64" + - "--platform=linux/amd64,linux/arm64" + images: + - "docker.io/pgconfig/pgconfigctl" + - "ghcr.io/pgconfig/pgconfigctl" + tags: + - "v{{ .Version }}" + - "v{{ .Major }}.{{ .Minor }}" + - "v{{ .Major }}" + - "latest" + labels: + "org.opencontainers.image.created": "{{.Date}}" + "org.opencontainers.image.title": "pgconfig-{{.ProjectName}}" + "org.opencontainers.image.website": "pgconfig.org" + "org.opencontainers.image.revision": "{{.FullCommit}}" + "org.opencontainers.image.version": "{{.Version}}" - - dockerfile: cmd/api/Dockerfile - goarch: arm64 - id: api-arm64 - ids: - - api - image_templates: - - "docker.io/pgconfig/api:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:arm64-v{{ .Commit }}" - - build_flag_templates: - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title=pgconfig-{{.ProjectName}}" - - "--label=org.opencontainers.image.website=pgconfig.org" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--platform=linux/arm64" - - extra_files: - - rules.yml - - pg-docs.yml - - dockerfile: cmd/api/Dockerfile - goarch: amd64 - id: api-amd64 + - id: api ids: - api - image_templates: - - "docker.io/pgconfig/api:amd64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:amd64-v{{ .Commit }}" - - "registry.heroku.com/{{ .Env.HEROKU_APP_NAME }}/web:latest" + dockerfile: cmd/api/Dockerfile + use: buildx build_flag_templates: - - "--label=org.opencontainers.image.created={{.Date}}" - - "--label=org.opencontainers.image.title=pgconfig-{{.ProjectName}}" - - "--label=org.opencontainers.image.website=pgconfig.org" - - "--label=org.opencontainers.image.revision={{.FullCommit}}" - - "--label=org.opencontainers.image.version={{.Version}}" - - "--platform=linux/amd64" + - "--platform=linux/amd64,linux/arm64" extra_files: - rules.yml - pg-docs.yml -docker_manifests: - - name_template: docker.io/pgconfig/api:v{{ .Tag }} - image_templates: - - "docker.io/pgconfig/api:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/api:v{{ .Major }}.{{ .Minor }}" - image_templates: - - "docker.io/pgconfig/api:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/api:v{{ .Major }}" - image_templates: - - "docker.io/pgconfig/api:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/api:latest" - image_templates: - - "docker.io/pgconfig/api:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/pgconfigctl:v{{ .Tag }}" - image_templates: - - "docker.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/pgconfigctl:v{{ .Major }}.{{ .Minor }}" - image_templates: - - "docker.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/pgconfigctl:v{{ .Major }}" - image_templates: - - "docker.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "docker.io/pgconfig/pgconfigctl:latest" - image_templates: - - "docker.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "docker.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: ghcr.io/pgconfig/api:v{{ .Tag }} - image_templates: - - "ghcr.io/pgconfig/api:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/api:v{{ .Major }}.{{ .Minor }}" - image_templates: - - "ghcr.io/pgconfig/api:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/api:v{{ .Major }}" - image_templates: - - "ghcr.io/pgconfig/api:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/api:latest" - image_templates: - - "ghcr.io/pgconfig/api:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/api:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/pgconfigctl:v{{ .Tag }}" - image_templates: - - "ghcr.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/pgconfigctl:v{{ .Major }}.{{ .Minor }}" - image_templates: - - "ghcr.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/pgconfigctl:v{{ .Major }}" - image_templates: - - "ghcr.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" - - name_template: "ghcr.io/pgconfig/pgconfigctl:latest" - image_templates: - - "ghcr.io/pgconfig/pgconfigctl:arm64-v{{ .Commit }}" - - "ghcr.io/pgconfig/pgconfigctl:amd64-v{{ .Commit }}" + images: + - "docker.io/pgconfig/api" + - "ghcr.io/pgconfig/api" + - "registry.heroku.com/{{ .Env.HEROKU_APP_NAME }}/web" + tags: + - "v{{ .Version }}" + - "v{{ .Major }}.{{ .Minor }}" + - "v{{ .Major }}" + - "latest" + labels: + "org.opencontainers.image.created": "{{.Date}}" + "org.opencontainers.image.title": "pgconfig-{{.ProjectName}}" + "org.opencontainers.image.website": "pgconfig.org" + "org.opencontainers.image.revision": "{{.FullCommit}}" + "org.opencontainers.image.version": "{{.Version}}" diff --git a/cmd/api/Dockerfile b/cmd/api/Dockerfile index d1e8107..f2c979a 100644 --- a/cmd/api/Dockerfile +++ b/cmd/api/Dockerfile @@ -1,12 +1,13 @@ FROM alpine:3.13 as builder FROM scratch +ARG TARGETPLATFORM EXPOSE 3000 ENV PORT=3000 COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ WORKDIR /app - COPY api /app + COPY ${TARGETPLATFORM}/api /app COPY *.yml /app ENTRYPOINT [ "/app/api" ] diff --git a/cmd/pgconfigctl/Dockerfile b/cmd/pgconfigctl/Dockerfile index 57e24b2..2d1048c 100644 --- a/cmd/pgconfigctl/Dockerfile +++ b/cmd/pgconfigctl/Dockerfile @@ -1,3 +1,4 @@ FROM scratch -COPY pgconfigctl / +ARG TARGETPLATFORM +COPY ${TARGETPLATFORM}/pgconfigctl / CMD ["/pgconfigctl"] \ No newline at end of file From 058b4410b4934f6922636dc5898f7f2590719a66 Mon Sep 17 00:00:00 2001 From: Sebastian Webber Date: Sun, 28 Dec 2025 03:15:43 -0300 Subject: [PATCH 3/3] fix(config): quote keys in rules.yml and add load test --- cmd/api/main.go | 4 +++- rules.yml | 34 +++++++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/cmd/api/main.go b/cmd/api/main.go index 1e5781d..0a7c8f7 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -32,7 +32,7 @@ func getDefaultPort(envName string) int { return out } -func init() { +func initAPI() { flag.IntVar(&port, "port", getDefaultPort("PORT"), "Listen port") flag.StringVar(&rulesFile, "rules-file", "./rules.yml", "Rules file") flag.StringVar(&docsFile, "docs-file", "./pg-docs.yml", "Rules file") @@ -42,6 +42,8 @@ func init() { } func main() { + initAPI() + log.Printf("PGConfig API - %s\n", version.Pretty()) app := routes.New() diff --git a/rules.yml b/rules.yml index 7df031a..8a5ca46 100644 --- a/rules.yml +++ b/rules.yml @@ -68,18 +68,18 @@ categories: io_method: abstract: Controls the asynchronous I/O implementation used by PostgreSQL. Options are "worker" (dedicated I/O worker processes), "io_uring" (Linux io_uring interface), and "sync" (traditional synchronous I/O). recomendations: - Tuning AIO in PostgreSQL 18 - Tomas Vondra: https://vondra.me/posts/tuning-aio-in-postgresql-18/ - Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze: https://pganalyze.com/blog/postgres-18-async-io - PostgreSQL 18: Better I/O performance with AIO - Cybertec: https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ - PostgreSQL 18 Asynchronous I/O - Neon: https://neon.com/postgresql/postgresql-18/asynchronous-io - PostgreSQL 18: The AIO Revolution - dev.to: https://dev.to/mattleads/postgresql-18-the-aio-revolution-uuidv7-and-the-path-to-unprecedented-performance-415m + "Tuning AIO in PostgreSQL 18 - Tomas Vondra": https://vondra.me/posts/tuning-aio-in-postgresql-18/ + "Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze": https://pganalyze.com/blog/postgres-18-async-io + "PostgreSQL 18: Better I/O performance with AIO - Cybertec": https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ + "PostgreSQL 18 Asynchronous I/O - Neon": https://neon.com/postgresql/postgresql-18/asynchronous-io + "PostgreSQL 18: The AIO Revolution - dev.to": https://dev.to/mattleads/postgresql-18-the-aio-revolution-uuidv7-and-the-path-to-unprecedented-performance-415m io_workers: abstract: Number of background I/O worker processes used when io_method is set to "worker". Determines how many concurrent I/O operations can be performed asynchronously. recomendations: - Tuning AIO in PostgreSQL 18 - Tomas Vondra: https://vondra.me/posts/tuning-aio-in-postgresql-18/ - Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze: https://pganalyze.com/blog/postgres-18-async-io - PostgreSQL 18: Better I/O performance with AIO - Cybertec: https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ - PostgreSQL 18 Asynchronous I/O - Neon: https://neon.com/postgresql/postgresql-18/asynchronous-io + "Tuning AIO in PostgreSQL 18 - Tomas Vondra": https://vondra.me/posts/tuning-aio-in-postgresql-18/ + "Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze": https://pganalyze.com/blog/postgres-18-async-io + "PostgreSQL 18: Better I/O performance with AIO - Cybertec": https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ + "PostgreSQL 18 Asynchronous I/O - Neon": https://neon.com/postgresql/postgresql-18/asynchronous-io maintenance_io_concurrency: abstract: Sets the number of concurrent I/O operations that PostgreSQL expects can be executed simultaneously during maintenance operations such as VACUUM and CREATE INDEX. io_combine_limit: @@ -91,20 +91,20 @@ categories: abstract: Server-wide limit that clamps io_combine_limit, controlling the largest I/O size in operations that combine I/O. recomendations: "Allow io_combine_limit up to 1MB": https://www.postgresql.org/message-id/CA+hUKGKd=U1zSFYNjwBBrXV3NsqR2U8dCUrCBVeB0DQ8Vb8Dwg@mail.gmail.com - Tuning AIO in PostgreSQL 18 - Tomas Vondra: https://vondra.me/posts/tuning-aio-in-postgresql-18/ - Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze: https://pganalyze.com/blog/postgres-18-async-io - PostgreSQL 18: Better I/O performance with AIO - Cybertec: https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ - PostgreSQL 18 Asynchronous I/O - Neon: https://neon.com/postgresql/postgresql-18/asynchronous-io + "Tuning AIO in PostgreSQL 18 - Tomas Vondra": https://vondra.me/posts/tuning-aio-in-postgresql-18/ + "Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze": https://pganalyze.com/blog/postgres-18-async-io + "PostgreSQL 18: Better I/O performance with AIO - Cybertec": https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ + "PostgreSQL 18 Asynchronous I/O - Neon": https://neon.com/postgresql/postgresql-18/asynchronous-io The Ultimate PostgreSQL 18 Asynchronous I/O Tuning Checklist (With Examples): https://www.cybrosys.com/research-and-development/postgres/the-ultimate-postgresql-18-asynchronous-io-tuning-checklist-with-examples PostgreSQL 18 Asynchronous Disk I/O - Deep Dive Into Implementation: https://www.credativ.de/en/blog/postgresql-en/postgresql-18-asynchronous-disk-i-o-deep-dive-into-implementation/ io_max_concurrency: abstract: Maximum number of concurrent I/O requests that can be in flight at once. recomendations: "PostgreSQL 18 Beta 1 io_max_concurrency": https://www.postgresql.org/message-id/9673.1747250758@sss.pgh.pa.us - Tuning AIO in PostgreSQL 18 - Tomas Vondra: https://vondra.me/posts/tuning-aio-in-postgresql-18/ - Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze: https://pganalyze.com/blog/postgres-18-async-io - PostgreSQL 18: Better I/O performance with AIO - Cybertec: https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ - PostgreSQL 18 Asynchronous I/O - Neon: https://neon.com/postgresql/postgresql-18/asynchronous-io + "Tuning AIO in PostgreSQL 18 - Tomas Vondra": https://vondra.me/posts/tuning-aio-in-postgresql-18/ + "Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O - pganalyze": https://pganalyze.com/blog/postgres-18-async-io + "PostgreSQL 18: Better I/O performance with AIO - Cybertec": https://www.cybertec-postgresql.com/en/postgresql-18-better-i-o-performance-with-aio/ + "PostgreSQL 18 Asynchronous I/O - Neon": https://neon.com/postgresql/postgresql-18/asynchronous-io The Ultimate PostgreSQL 18 Asynchronous I/O Tuning Checklist (With Examples): https://www.cybrosys.com/research-and-development/postgres/the-ultimate-postgresql-18-asynchronous-io-tuning-checklist-with-examples PostgreSQL 18 Asynchronous Disk I/O - Deep Dive Into Implementation: https://www.credativ.de/en/blog/postgresql-en/postgresql-18-asynchronous-disk-i-o-deep-dive-into-implementation/ file_copy_method: