18 Commits

Author SHA1 Message Date
0cb2c00f43 fix(ci): update branch pattern in CI workflow
All checks were successful
CI / Lint, Typecheck & Test (push) Successful in 2m28s
Changed the branch pattern in the CI workflow from a specific feature branch to a wildcard pattern ("**") for broader applicability. This adjustment is part of ongoing testing and refinement of the CI process.
2026-03-13 21:44:18 +03:00
777c3b34bc fix(ci): replace dynamic matrix with explicit per-app jobs
All checks were successful
Deploy — Staging / Detect changed apps (push) Successful in 16s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m29s
Deploy — Staging / Build & push — storefront (push) Has been skipped
Deploy — Staging / Build & push — admin (push) Has been skipped
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
Gitea Actions does not evaluate fromJson() in matrix strategy — matrix.app
was always empty, breaking turbo prune. Replaced with two explicit jobs
(build-storefront, build-admin) each with a plain if: condition.

The deploy job uses always() + !contains(needs.*.result, 'failure') so it
runs when either build succeeded and skips when a build was cancelled/failed.
Parallelism is preserved — both apps still build simultaneously when both change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 16:35:10 +03:00
0bd0d90f45 feat(ci): skip build and deploy for unchanged apps
All checks were successful
Deploy — Staging / Detect changed apps (push) Successful in 16s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m26s
Deploy — Staging / Build & push — ${{ matrix.app }} (push) Has been skipped
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
Add a changes job that diffs HEAD~1..HEAD and outputs which apps were
affected. Build and deploy jobs consume the output:

- build matrix is restricted to changed apps only — unchanged apps are
  never built or pushed
- deploy pulls only rebuilt images and restarts only those containers

Shared triggers (packages/, convex/, package-lock.json, turbo.json) mark
both apps as changed since they affect the full dependency tree.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 16:15:58 +03:00
3396a79445 fix(storefront): pass NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY at build time
All checks were successful
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m27s
Deploy — Staging / Build & push — admin (push) Successful in 53s
Deploy — Staging / Build & push — storefront (push) Successful in 1m40s
Deploy — Staging / Deploy to staging VPS (push) Successful in 19s
Stripe publishable key must be baked into the client bundle. Added ARG/ENV
to storefront Dockerfile and --build-arg in the workflow build step, sourced
from STAGING_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY secret.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:50:09 +03:00
9f2e9afc63 fix(admin): pass missing Cloudinary and image-processing env vars
All checks were successful
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m31s
Deploy — Staging / Build & push — admin (push) Successful in 1m39s
Deploy — Staging / Build & push — storefront (push) Successful in 57s
Deploy — Staging / Deploy to staging VPS (push) Successful in 20s
NEXT_PUBLIC_CLOUDINARY_API_KEY and NEXT_PUBLIC_IMAGE_PROCESSING_API_URL are
NEXT_PUBLIC_* vars that must be baked in at build time — added as ARG/ENV in
admin Dockerfile and as --build-arg in the workflow build step.

CLOUDINARY_API_SECRET is a server-side secret — added to the deploy step's
env block, written to /opt/staging/.env via printf, and exposed to the admin
container via compose.yml environment block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 14:45:31 +03:00
64c0cd6af8 fix(deploy): write .env to /opt/staging not \$HOME/staging
All checks were successful
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m27s
Deploy — Staging / Build & push — admin (push) Successful in 54s
Deploy — Staging / Build & push — storefront (push) Successful in 55s
Deploy — Staging / Deploy to staging VPS (push) Successful in 20s
\$HOME in an unquoted heredoc expands on the runner (not the VPS), so the
VPS received the literal runner path (/root/staging/.env) which didn't exist.
Using the explicit /opt/staging/.env path (consistent with compose.yml and
mkdir) fixes the permission denied error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 13:04:40 +03:00
af8e14c545 fix(deploy): inject runtime secrets and force-recreate containers on deploy
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m33s
Deploy — Staging / Build & push — admin (push) Successful in 57s
Deploy — Staging / Build & push — storefront (push) Successful in 58s
Deploy — Staging / Deploy to staging VPS (push) Failing after 18s
- Add --force-recreate to podman compose up so stale containers are never
  reused across deploys when the image tag (staging) is reused
- Inject CLERK_SECRET_KEY and ADMIN_CLERK_SECRET_KEY from Gitea secrets into
  ~/staging/.env on the VPS via printf (variables expand on the runner before
  SSH, so secrets never touch VPS shell history; file gets chmod 600)
- Update compose.yml: storefront gets CLERK_SECRET_KEY, admin gets
  CLERK_SECRET_KEY mapped from ADMIN_CLERK_SECRET_KEY

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 12:42:06 +03:00
439d6d4455 fix(ci): fix YAML parse error in deploy workflow caused by inner heredoc
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 1m29s
Deploy — Staging / Build & push — admin (push) Successful in 54s
Deploy — Staging / Build & push — storefront (push) Successful in 53s
Deploy — Staging / Deploy to staging VPS (push) Failing after 24s
The compose file was written via a bash << 'COMPOSE' heredoc nested inside
the YAML run: | block scalar. Lines like "name: petloft-staging" at column 0
cause the YAML parser to break out of the block scalar early, making the
entire workflow file invalid YAML — Gitea silently drops invalid workflows,
so no jobs triggered at all.

Fix: move compose.yml to deploy/staging/compose.yml in the repo, substitute
${REGISTRY} on the runner, base64-encode the result, and decode it on the VPS
inside the SSH session. No inner heredoc needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 11:37:02 +03:00
b333047753 workflow trigger 2026-03-08 11:29:45 +03:00
0b9ac5cd46 fix(deploy): create /opt/staging and write compose.yml on every deploy
The VPS had no /opt/staging directory or compose file, causing the deploy
step to fail with "No such file or directory". Now the workflow:
- Creates /opt/staging if missing
- Writes compose.yml on every deploy (keeps it in sync with CI)
- Touches .env so podman compose doesn't error if no secrets file exists yet

Also adds deploy/staging/.env.example documenting runtime secrets that must
be set manually on the VPS after first deploy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 11:10:52 +03:00
5b0a727bce fix(ci): replace turbo-pruned lockfile with full root lockfile to fix @heroui/react missing in Docker
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m7s
Deploy — Staging / Build & push — admin (push) Successful in 3m20s
Deploy — Staging / Build & push — storefront (push) Failing after 2m30s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
turbo prune cannot fully parse the npm 11 lockfile format, causing it to
generate an incomplete out/package-lock.json that drops non-hoisted workspace
entries (apps/storefront/node_modules/@heroui/react and related packages).
Replacing it with the full root lockfile ensures npm ci in the Docker deps
stage installs all packages including non-hoisted ones.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 04:38:54 +03:00
829fec9ac1 fix(ci): use --load + docker push instead of --push for HTTP registry
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m8s
Deploy — Staging / Build & push — admin (push) Successful in 1m22s
Deploy — Staging / Build & push — storefront (push) Failing after 1m35s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
docker build --push uses buildkit's internal push which connects directly
to the registry over HTTPS, bypassing the Podman daemon. Since the Gitea
registry is HTTP-only, this fails with "server gave HTTP response to HTTPS client".

Switch to --load (exports image into Podman daemon) then docker push (goes
through the daemon which has insecure=true in registries.conf → uses HTTP).
Tag the SHA variant with docker tag before pushing both.

Also:
- Add NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME ARG/ENV to admin Dockerfile
- Add STAGING_ prefix note to both Dockerfiles builder stage
- Add STAGING_NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME to workflow env and
  pass it as --build-arg for admin builds only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 04:14:47 +03:00
6b63cbb6cd fix(ci): update Dockerfiles and workflow to include new Cloudinary environment variable
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m6s
Deploy — Staging / Build & push — admin (push) Failing after 2m7s
Deploy — Staging / Build & push — storefront (push) Failing after 1m35s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
- Added NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME to both admin and storefront Dockerfiles to ensure it is available during the build process.
- Updated deploy-staging.yml to pass the new Cloudinary variable as a build argument.
- Clarified comments regarding the handling of NEXT_PUBLIC_* variables and Gitea secret prefixes.

This change enhances the build configuration for both applications, ensuring all necessary environment variables are correctly passed during the Docker build process.
2026-03-08 04:05:01 +03:00
bc7306fea4 fix(ci): pass NEXT_PUBLIC build args and fix docker push
Some checks failed
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m11s
Deploy — Staging / Build & push — admin (push) Failing after 2m8s
Deploy — Staging / Build & push — storefront (push) Failing after 1m42s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
Two issues in the admin (and upcoming storefront) build:

1. Missing Clerk publishableKey during prerender
   NEXT_PUBLIC_* vars are baked into the client bundle at build time. If absent,
   Next.js SSG fails with "@clerk/clerk-react: Missing publishableKey".
   Added ARG + ENV in both Dockerfiles builder stage and pass them via
   --build-arg in the workflow. Admin and storefront use different Clerk
   instances so the key is selected per matrix.app with a shell conditional.

2. "No output specified with docker-container driver" warning
   setup-buildx-action with driver:docker was not switching the driver in the
   Podman environment. Removed the step and switched to docker build --push
   which pushes directly during the build, eliminating the separate push steps
   and the missing-output warning.

New secrets required:
  STAGING_NEXT_PUBLIC_CONVEX_URL
  STAGING_NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY        (storefront)
  STAGING_ADMIN_NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY  (admin)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 03:31:58 +03:00
7a6da4f18f fix(ci): fix convex missing from prune output and npm version mismatch
Some checks failed
CI / Lint, Typecheck & Test (push) Successful in 2m5s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m5s
Deploy — Staging / Build & push — admin (push) Failing after 3m11s
Deploy — Staging / Build & push — storefront (push) Failing after 2m23s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
Two root causes for the Docker build failures:

1. convex/_generated/api not found (both apps)
   turbo prune only traces npm workspace packages; the root convex/ directory
   is not a workspace package so it is excluded from out/full/. Copy it
   manually into the prune output after turbo prune runs.

2. @heroui/react not found (storefront)
   package-lock.json was generated with npm@11 but node:20-alpine ships
   npm@10. turbo warns it cannot parse the npm 11 lockfile and generates an
   incomplete out/package-lock.json, causing npm ci inside Docker to miss
   packages. Upgrade npm to 11 in the deps stage of both Dockerfiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 03:16:29 +03:00
fc5f98541b fix(ci): fix deploy-staging registry and buildx driver issues
Some checks failed
CI / Lint, Typecheck & Test (push) Successful in 2m6s
Deploy — Staging / Lint, Typecheck & Test (push) Successful in 2m56s
Deploy — Staging / Build & push — admin (push) Failing after 3m7s
Deploy — Staging / Build & push — storefront (push) Failing after 2m30s
Deploy — Staging / Deploy to staging VPS (push) Has been skipped
- Remove top-level env.REGISTRY — Gitea does not expand secrets in
  workflow-level env blocks; reference secrets.STAGING_REGISTRY directly
- Add docker/setup-buildx-action with driver: docker to avoid the
  docker-container driver which requires --privileged on rootless Podman
- Update secret names comment to clarify STAGING_ prefix convention
  (Gitea has no environment-level secrets, so prefixes distinguish staging/prod)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 02:55:41 +03:00
79640074cd feat(ci): add Gitea CI workflow for staging deployment
- Introduced a new workflow in deploy-staging.yml to automate the deployment process for the staging environment.
- The workflow includes steps for CI tasks (linting, type checking, testing), building and pushing Docker images for storefront and admin applications, and deploying to a VPS.
- Configured environment variables and secrets for secure access to the Docker registry and VPS.

This commit enhances the CI/CD pipeline by streamlining the deployment process to the staging environment.
2026-03-08 01:42:57 +03:00
51663df27d ci: add Gitea CI workflow and track Convex generated types
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m11s
- Add .gitea/workflows/ci.yml — runs lint, typecheck, and tests on every push
- Remove convex/_generated from .gitignore and commit the generated files so CI
  has the type information it needs without requiring a live Convex backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 00:25:45 +03:00