From 725f7493a4820718622d0ed2e92498a3fbbcd7a5 Mon Sep 17 00:00:00 2001 From: Mike de Geofroy Date: Tue, 5 May 2026 20:55:09 +0300 Subject: [PATCH 1/3] feat: configurable POSTGRES_SSLMODE + ghcr publishing Backend & dashboard-backend gain a POSTGRES_SSLMODE env (default disable for existing dev/CI flows; production overrides to require for managed Postgres that rejects non-SSL). Shared deploy.yaml gains push_to_ghcr/ghcr_image_name inputs. When opted in, images are pushed to ghcr.io with main-- tag for Flux ImagePolicy in addition to the existing Docker Hub publish + Portainer webhook so swarm keeps working during the k8s cutover. Opted in: server, bot, miniapp, storybook. Dashboard, dashboard-ui, landing untouched. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/deploy-bot.yaml | 1 + .github/workflows/deploy-miniapp.yaml | 1 + .github/workflows/deploy-server.yaml | 1 + .github/workflows/deploy-storybook.yaml | 1 + .github/workflows/deploy.yaml | 37 +++++++++++++++++++++++++ dashboard/cmd/config/config.go | 4 ++- server/cmd/server/config/config.go | 4 ++- 7 files changed, 47 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-bot.yaml b/.github/workflows/deploy-bot.yaml index 5b0b000..b9c0636 100644 --- a/.github/workflows/deploy-bot.yaml +++ b/.github/workflows/deploy-bot.yaml @@ -24,3 +24,4 @@ jobs: image_name: 'dishdash-bot' environment: ${{ github.event.inputs.environment }} secret-service-hash: ${{ github.event.inputs.environment == 'PROD' && 'BOT_SERVICE_HASH' || 'BOT_SERVICE_HASH_DEV' }} + push_to_ghcr: true diff --git a/.github/workflows/deploy-miniapp.yaml b/.github/workflows/deploy-miniapp.yaml index 489b6e1..4bd3255 100644 --- a/.github/workflows/deploy-miniapp.yaml +++ b/.github/workflows/deploy-miniapp.yaml @@ -24,3 +24,4 @@ jobs: image_name: 'dishdash-miniapp' environment: ${{ github.event.inputs.environment }} secret-service-hash: ${{ github.event.inputs.environment == 'PROD' && 'MINIAPP_SERVICE_HASH' || 'MINIAPP_SERVICE_HASH_DEV' }} + push_to_ghcr: true diff --git a/.github/workflows/deploy-server.yaml b/.github/workflows/deploy-server.yaml index 39a209e..292e53a 100644 --- a/.github/workflows/deploy-server.yaml +++ b/.github/workflows/deploy-server.yaml @@ -28,3 +28,4 @@ jobs: image_name: 'dishdash-backend' environment: ${{ github.event.inputs.environment }} secret-service-hash: ${{ github.event.inputs.environment == 'PROD' && 'SERVER_SERVICE_HASH' || 'SERVER_SERVICE_HASH_DEV' }} + push_to_ghcr: true diff --git a/.github/workflows/deploy-storybook.yaml b/.github/workflows/deploy-storybook.yaml index 514b065..8b1e481 100644 --- a/.github/workflows/deploy-storybook.yaml +++ b/.github/workflows/deploy-storybook.yaml @@ -24,3 +24,4 @@ jobs: image_name: 'dishdash-storybook' environment: ${{ github.event.inputs.environment }} secret-service-hash: ${{ github.event.inputs.environment == 'PROD' && 'STORYBOOK_SERVICE_HASH' || 'STORYBOOK_SERVICE_HASH_DEV' }} + push_to_ghcr: true diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 85ca648..5543f62 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -26,6 +26,16 @@ on: required: true description: name of secret value type: string + push_to_ghcr: + required: false + type: boolean + default: false + description: also publish to ghcr.io with main-- tag for Flux ImagePolicy + ghcr_image_name: + required: false + type: string + default: "" + description: name of image on ghcr (defaults to image_name) jobs: push_to_registry: @@ -51,6 +61,7 @@ jobs: run: | calculatedSha=$(git rev-parse --short ${{ github.sha }}) echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV + echo "BUILD_TS=$(date +%s)" >> $GITHUB_ENV - name: Log in to Docker Hub uses: docker/login-action@v2 @@ -58,6 +69,14 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} + - name: Log in to GHCR + if: inputs.push_to_ghcr + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Define Docker tags run: | if [ "${{ inputs.environment }}" == "DEV" ]; then @@ -65,9 +84,25 @@ jobs: elif [ "${{ inputs.environment }}" == "PROD" ]; then echo "VERSION_TAG=latest" >> $GITHUB_ENV fi + GHCR_NAME="${{ inputs.ghcr_image_name }}" + if [ -z "$GHCR_NAME" ]; then GHCR_NAME="${{ inputs.image_name }}"; fi + REPO_OWNER_LC="$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" + echo "GHCR_REPO=ghcr.io/$REPO_OWNER_LC/$GHCR_NAME" >> $GITHUB_ENV - name: Build and push Docker image id: push + if: ${{ !inputs.push_to_ghcr }} + uses: docker/build-push-action@v5 + with: + context: ./${{ inputs.context_path }} + file: ./${{ inputs.dockerfile_path }}/Dockerfile + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/${{ inputs.image_name }}:${{ env.VERSION_TAG }} + ${{ secrets.DOCKER_USERNAME }}/${{ inputs.image_name }}:${{ env.COMMIT_SHORT_SHA }} + + - name: Build and push to Docker Hub + GHCR + if: inputs.push_to_ghcr uses: docker/build-push-action@v5 with: context: ./${{ inputs.context_path }} @@ -76,6 +111,8 @@ jobs: tags: | ${{ secrets.DOCKER_USERNAME }}/${{ inputs.image_name }}:${{ env.VERSION_TAG }} ${{ secrets.DOCKER_USERNAME }}/${{ inputs.image_name }}:${{ env.COMMIT_SHORT_SHA }} + ${{ env.GHCR_REPO }}:${{ env.VERSION_TAG }} + ${{ env.GHCR_REPO }}:main-${{ env.COMMIT_SHORT_SHA }}-${{ env.BUILD_TS }} - name: Docker hub push notification uses: containrrr/shoutrrr-action@v1 diff --git a/dashboard/cmd/config/config.go b/dashboard/cmd/config/config.go index 8c1fd08..ca84493 100644 --- a/dashboard/cmd/config/config.go +++ b/dashboard/cmd/config/config.go @@ -22,6 +22,7 @@ type Config struct { Host string `envconfig:"POSTGRES_HOST"` Port uint16 `envconfig:"POSTGRES_PORT"` Database string `envconfig:"POSTGRES_DB"` + SSLMode string `default:"disable" envconfig:"POSTGRES_SSLMODE"` } Auth struct { ApiToken string `envconfig:"API_TOKEN"` @@ -68,12 +69,13 @@ func Print() { func (c Config) DBUrl() string { return fmt.Sprintf( - "postgres://%s:%s@%s:%d/%s?sslmode=disable", + "postgres://%s:%s@%s:%d/%s?sslmode=%s", C.DB.User, C.DB.Password, C.DB.Host, C.DB.Port, C.DB.Database, + C.DB.SSLMode, ) } diff --git a/server/cmd/server/config/config.go b/server/cmd/server/config/config.go index 2b2b789..2b79c5d 100644 --- a/server/cmd/server/config/config.go +++ b/server/cmd/server/config/config.go @@ -23,6 +23,7 @@ type Config struct { Host string `envconfig:"POSTGRES_HOST"` Port uint16 `envconfig:"POSTGRES_PORT"` Database string `envconfig:"POSTGRES_DB"` + SSLMode string `default:"disable" envconfig:"POSTGRES_SSLMODE"` AutoMigrate bool `envconfig:"POSTGRES_AUTOMIGRATE"` } Defaults struct { @@ -74,12 +75,13 @@ func Print() { func (c Config) DBUrl() string { return fmt.Sprintf( - "postgres://%s:%s@%s:%d/%s?sslmode=disable", + "postgres://%s:%s@%s:%d/%s?sslmode=%s", C.DB.User, C.DB.Password, C.DB.Host, C.DB.Port, C.DB.Database, + C.DB.SSLMode, ) } From cbaee61b097e2eeea9f36bdccff70ea50ff56727 Mon Sep 17 00:00:00 2001 From: Mike de Geofroy Date: Tue, 5 May 2026 21:03:18 +0300 Subject: [PATCH 2/3] ci(server): build golangci-lint from source via active Go Pinned binary build (v1.63.4 = Go 1.23) can't parse Go 1.26 syntax in the codebase, producing ~200 cascading typecheck errors. Switching to install-mode: goinstall so the linter is compiled with whatever Go version setup-go installed (currently stable). Bumped action to v6 for goinstall support. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci-server.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-server.yaml b/.github/workflows/ci-server.yaml index fd52196..105d951 100644 --- a/.github/workflows/ci-server.yaml +++ b/.github/workflows/ci-server.yaml @@ -31,9 +31,10 @@ jobs: go build -v ./... - name: Lint - uses: golangci/golangci-lint-action@v4 + uses: golangci/golangci-lint-action@v6 with: - version: v1.63.4 + version: v1.64.8 + install-mode: goinstall working-directory: ./server - name: Unit test From a0b6bec7032bdc85912ca8095a36efdcf97816f0 Mon Sep 17 00:00:00 2001 From: Mike de Geofroy Date: Tue, 5 May 2026 21:05:08 +0300 Subject: [PATCH 3/3] ci(server): rerun on workflow file changes + manual dispatch Add .github/workflows/ci-server.yaml to the path filter so CI re-runs when the workflow itself is edited. Add workflow_dispatch for manual triggers. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci-server.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-server.yaml b/.github/workflows/ci-server.yaml index 105d951..e14238a 100644 --- a/.github/workflows/ci-server.yaml +++ b/.github/workflows/ci-server.yaml @@ -1,14 +1,17 @@ name: ci-server -on: +on: workflow_call: + workflow_dispatch: push: paths: - 'server/**' + - '.github/workflows/ci-server.yaml' pull_request: paths: - 'server/**' + - '.github/workflows/ci-server.yaml' jobs: build: