Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
344319f456 | ||
|
|
ac735a627e |
No files matched your search
+40
-42
@@ -1,7 +1,7 @@
|
||||
# Manual PROD deploy to Portainer.
|
||||
# Manual PROD deploy to Dockerloid.
|
||||
#
|
||||
# This does NOT build — build.yml already builds + pushes the api/web images.
|
||||
# This workflow (re)applies the deploy/*.stack.yml files to the Portainer Swarm.
|
||||
# This workflow (re)applies the deploy/*.stack.yml files to the Dockerloid Swarm.
|
||||
# Trigger it by hand from the Actions tab ("Run workflow") and choose:
|
||||
# - tag: which already-published image tag to ship (default: latest)
|
||||
# - scope: how much to deploy
|
||||
@@ -21,7 +21,7 @@
|
||||
# own workflow, .gitea/workflows/deploy-galactus.yml.
|
||||
#
|
||||
# cssnr/portainer-stack-deploy-action creates each stack on first run and updates
|
||||
# it on every run, so no manual stack pre-creation in the Portainer UI. On a
|
||||
# it on every run, so no manual stack pre-creation in the Dockerloid UI. On a
|
||||
# `full` deploy the db + minio stacks are applied BEFORE the app (the API depends
|
||||
# on them). db + minio are stateful + pinned to node label jorgecuadros_db=true
|
||||
# (see their stack files) — re-applying them is idempotent and keeps their data.
|
||||
@@ -29,13 +29,13 @@
|
||||
# Prereqs (once):
|
||||
# - one swarm node labelled jorgecuadros_db=true (db + minio + api pin there).
|
||||
# - Gitea repo secrets set (Settings > Actions > Secrets):
|
||||
# # Portainer
|
||||
# PORTAINER_URL https://192.168.4.212:9443
|
||||
# PORTAINER_API_KEY Portainer access token
|
||||
# PORTAINER_ENDPOINT_ID 2 (the local Swarm endpoint)
|
||||
# PORTAINER_APP_STACK_NAME e.g. jorgecuadros-prod-app
|
||||
# PORTAINER_DB_STACK_NAME e.g. jorgecuadros-prod-db (full only)
|
||||
# PORTAINER_MINIO_STACK_NAME e.g. jorgecuadros-prod-minio (full only)
|
||||
# # Dockerloid
|
||||
# DOCKERLOID_URL http://192.168.4.212:7777
|
||||
# DOCKERLOID_API_KEY Dockerloid access token
|
||||
# DOCKERLOID_ENDPOINT_ID 2 (the local Swarm endpoint)
|
||||
# DOCKERLOID_APP_STACK_NAME e.g. jorgecuadros-prod-app
|
||||
# DOCKERLOID_DB_STACK_NAME e.g. jorgecuadros-prod-db (full only)
|
||||
# DOCKERLOID_MINIO_STACK_NAME e.g. jorgecuadros-prod-minio (full only)
|
||||
# # App runtime
|
||||
# DATABASE_URL mysql://jorgecuadros:<pass>@192.168.4.212:3306/jorgecuadros
|
||||
# SESSION_SECRET 64-hex (openssl rand -hex 32)
|
||||
@@ -48,7 +48,7 @@
|
||||
# # Database stack (full only)
|
||||
# MYSQL_PASSWORD app-user password (matches DATABASE_URL)
|
||||
# MYSQL_ROOT_PASSWORD mysql root password
|
||||
# - the runner must reach Portainer (9443). It should also reach MySQL (3306)
|
||||
# - runner must reach Dockerloid API (7777) and MySQL (3306)
|
||||
# for the migrate step, but that is no longer load-bearing: dispatch with
|
||||
# skip_migrate=true and the api container applies the migrations itself at
|
||||
# start (docker/api-entrypoint.sh). `migrate deploy` is idempotent, so the
|
||||
@@ -59,7 +59,7 @@
|
||||
# npx prisma@5 migrate resolve --applied 0000_init \
|
||||
# --schema packages/database/prisma/schema.prisma
|
||||
|
||||
name: Deploy to Portainer
|
||||
name: Deploy via Dockerloid
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -109,12 +109,12 @@ jobs:
|
||||
# action's input, not the secret you forgot.
|
||||
- name: Preflight — required secrets
|
||||
env:
|
||||
PORTAINER_URL: ${{ secrets.PORTAINER_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.PORTAINER_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
PORTAINER_APP_STACK_NAME: ${{ secrets.PORTAINER_APP_STACK_NAME }}
|
||||
PORTAINER_DB_STACK_NAME: ${{ secrets.PORTAINER_DB_STACK_NAME }}
|
||||
PORTAINER_MINIO_STACK_NAME: ${{ secrets.PORTAINER_MINIO_STACK_NAME }}
|
||||
PORTAINER_URL: ${{ secrets.DOCKERLOID_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
DOCKERLOID_APP_STACK_NAME: ${{ secrets.DOCKERLOID_APP_STACK_NAME }}
|
||||
DOCKERLOID_DB_STACK_NAME: ${{ secrets.DOCKERLOID_DB_STACK_NAME }}
|
||||
DOCKERLOID_MINIO_STACK_NAME: ${{ secrets.DOCKERLOID_MINIO_STACK_NAME }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
SESSION_SECRET: ${{ secrets.SESSION_SECRET }}
|
||||
APP_API_ORIGIN: ${{ secrets.APP_API_ORIGIN }}
|
||||
@@ -127,11 +127,11 @@ jobs:
|
||||
SCOPE: ${{ github.event.inputs.scope }}
|
||||
run: |
|
||||
REQUIRED="PORTAINER_URL PORTAINER_API_KEY PORTAINER_ENDPOINT_ID
|
||||
PORTAINER_APP_STACK_NAME DATABASE_URL SESSION_SECRET
|
||||
DOCKERLOID_APP_STACK_NAME DATABASE_URL SESSION_SECRET
|
||||
APP_API_ORIGIN APP_WEB_ORIGIN APP_S3_ENDPOINT
|
||||
MINIO_ROOT_USER MINIO_ROOT_PASSWORD MYSQL_ROOT_PASSWORD"
|
||||
if [ "$SCOPE" = "full" ]; then
|
||||
REQUIRED="$REQUIRED PORTAINER_DB_STACK_NAME PORTAINER_MINIO_STACK_NAME
|
||||
REQUIRED="$REQUIRED DOCKERLOID_DB_STACK_NAME DOCKERLOID_MINIO_STACK_NAME
|
||||
MYSQL_PASSWORD"
|
||||
fi
|
||||
missing=""
|
||||
@@ -151,12 +151,12 @@ jobs:
|
||||
if: ${{ github.event.inputs.scope == 'full' }}
|
||||
uses: cssnr/portainer-stack-deploy-action@v1
|
||||
with:
|
||||
url: ${{ secrets.PORTAINER_URL }}
|
||||
token: ${{ secrets.PORTAINER_API_KEY }}
|
||||
name: ${{ secrets.PORTAINER_DB_STACK_NAME }}
|
||||
url: ${{ secrets.DOCKERLOID_URL }}
|
||||
token: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
name: ${{ secrets.DOCKERLOID_DB_STACK_NAME }}
|
||||
file: deploy/jorgecuadros-db.stack.yml
|
||||
type: file
|
||||
endpoint: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
endpoint: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
env_data: |
|
||||
{
|
||||
"MYSQL_SERVER_ID": "1",
|
||||
@@ -172,12 +172,12 @@ jobs:
|
||||
if: ${{ github.event.inputs.scope == 'full' }}
|
||||
uses: cssnr/portainer-stack-deploy-action@v1
|
||||
with:
|
||||
url: ${{ secrets.PORTAINER_URL }}
|
||||
token: ${{ secrets.PORTAINER_API_KEY }}
|
||||
name: ${{ secrets.PORTAINER_MINIO_STACK_NAME }}
|
||||
url: ${{ secrets.DOCKERLOID_URL }}
|
||||
token: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
name: ${{ secrets.DOCKERLOID_MINIO_STACK_NAME }}
|
||||
file: deploy/jorgecuadros-minio.stack.yml
|
||||
type: file
|
||||
endpoint: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
endpoint: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
env_data: |
|
||||
{
|
||||
"MINIO_API_PORT": "9000",
|
||||
@@ -192,9 +192,9 @@ jobs:
|
||||
# unreachable by the only restore path this platform has.
|
||||
- name: Pre-migrate backup
|
||||
env:
|
||||
PORTAINER_URL: ${{ secrets.PORTAINER_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.PORTAINER_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
PORTAINER_URL: ${{ secrets.DOCKERLOID_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
# The dump runs as root: --single-transaction issues FLUSH TABLES,
|
||||
# which needs the global RELOAD privilege the application user
|
||||
@@ -202,9 +202,8 @@ jobs:
|
||||
MYSQL_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }}
|
||||
BACKUP_TAG: ${{ github.event.inputs.tag }}
|
||||
ALLOW_MISSING_CONTAINER: ${{ github.event.inputs.bootstrap }}
|
||||
# Portainer serves a self-signed certificate. Scoped to this step
|
||||
# only, which does nothing but talk to Portainer.
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
||||
# Dockerloid uses HTTP on the LAN; this step does not need a TLS bypass.
|
||||
# Requests in this step go only to the Dockerloid API.
|
||||
run: node deploy/scripts/pre-migrate-backup.mjs
|
||||
|
||||
# --- schema, forward-only ---------------------------------------------
|
||||
@@ -234,28 +233,27 @@ jobs:
|
||||
# serving an older build of the same tag.
|
||||
- name: Pull images
|
||||
env:
|
||||
PORTAINER_URL: ${{ secrets.PORTAINER_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.PORTAINER_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
PORTAINER_URL: ${{ secrets.DOCKERLOID_URL }}
|
||||
PORTAINER_API_KEY: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
PORTAINER_ENDPOINT_ID: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
REGISTRY: ${{ env.REGISTRY }}
|
||||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
IMAGES: ${{ github.repository_owner }}/jorgecuadros-api,${{ github.repository_owner }}/jorgecuadros-web
|
||||
TAG: ${{ github.event.inputs.tag }}
|
||||
NODE_TLS_REJECT_UNAUTHORIZED: "0"
|
||||
run: node deploy/scripts/pull-images.mjs
|
||||
|
||||
# --- always: the app (web + api) -------------------------------------
|
||||
- name: Deploy app stack
|
||||
uses: cssnr/portainer-stack-deploy-action@v1
|
||||
with:
|
||||
url: ${{ secrets.PORTAINER_URL }}
|
||||
token: ${{ secrets.PORTAINER_API_KEY }}
|
||||
name: ${{ secrets.PORTAINER_APP_STACK_NAME }}
|
||||
url: ${{ secrets.DOCKERLOID_URL }}
|
||||
token: ${{ secrets.DOCKERLOID_API_KEY }}
|
||||
name: ${{ secrets.DOCKERLOID_APP_STACK_NAME }}
|
||||
file: deploy/jorgecuadros-app.stack.yml
|
||||
type: file
|
||||
pull: true
|
||||
endpoint: ${{ secrets.PORTAINER_ENDPOINT_ID }}
|
||||
endpoint: ${{ secrets.DOCKERLOID_ENDPOINT_ID }}
|
||||
# NOTE: the block below is parsed as JSON — no comments inside it.
|
||||
#
|
||||
# API_ORIGIN is deliberately absent. The browser derives the API origin
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# Canonical internal MySQL for the Jorge Cuadros platform.
|
||||
#
|
||||
# Target: Portainer "local" endpoint on cubex (192.168.4.212:9443), which is a
|
||||
# 3-node Docker Swarm. This is the source-of-truth database from the plan's
|
||||
# Target: cubex local endpoint, a 3-node Docker Swarm. The cubex workflow deploys
|
||||
# through Dockerloid; the separate Galactus workflow uses its own Portainer. This
|
||||
# is the source-of-truth database from the plan's
|
||||
# "internal server" — the migration transform+load and the NestJS API both
|
||||
# point at it, and (later) it becomes the replication SOURCE for the VPS.
|
||||
#
|
||||
@@ -25,7 +26,7 @@
|
||||
# and MySQL will always run there, reusing the same volume.
|
||||
#
|
||||
# Secrets (MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD) are injected at deploy time via
|
||||
# Portainer env_data / stack environment, not committed here.
|
||||
# The stack action env_data / stack environment, not committed here.
|
||||
|
||||
version: "3.8"
|
||||
|
||||
|
||||
Reference in new issue
Block a user