diff --git a/.github/workflows/deploy-dev2.yml b/.github/workflows/deploy-dev2.yml new file mode 100644 index 00000000..de6feb6f --- /dev/null +++ b/.github/workflows/deploy-dev2.yml @@ -0,0 +1,60 @@ +# Ship every merge to dev2, where sh1pt.com runs since it left Railway (which +# deployed on merge by itself). The box pulls the merged commit, rebuilds the +# image(s) from this repo and restarts the compose stack under +# /home/anthony/www/sh1pt.com. Generated by cli-tools/dev2/dev2-site scaffold. +name: Deploy to dev2 + +on: + push: + branches: [master] + workflow_dispatch: + inputs: + ref: + description: Git ref to deploy (defaults to the pushed commit) + required: false + type: string + +concurrency: + group: deploy-dev2 + cancel-in-progress: false + +jobs: + deploy: + runs-on: ubuntu-latest + timeout-minutes: 45 + steps: + # ${{ }} values go through env, never straight into a run: body. + - name: Resolve target revision + id: rev + env: + REF: ${{ inputs.ref || github.sha }} + run: echo "sha=$REF" >> "$GITHUB_OUTPUT" + + - name: Set up ssh + env: + SSH_KEY: ${{ secrets.DEV2_SSH_KEY }} + KNOWN_HOSTS: ${{ secrets.DEV2_KNOWN_HOSTS }} + run: | + install -d -m 700 ~/.ssh + printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519 + chmod 600 ~/.ssh/id_ed25519 + printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts + chmod 644 ~/.ssh/known_hosts + + - name: Deploy + env: + DEV2_USER: ${{ secrets.DEV2_USER }} + DEV2_HOST: ${{ secrets.DEV2_HOST }} + SHA: ${{ steps.rev.outputs.sha }} + run: | + ssh -o BatchMode=yes "$DEV2_USER@$DEV2_HOST" \ + /home/anthony/www/sh1pt.com/deploy-app.sh "$SHA" + + - name: Verify the site answers + run: | + for i in $(seq 1 10); do + code=$(curl -s -o /dev/null -w '%{http_code}' "https://sh1pt.com/" || true) + case "$code" in 2*|3*|401|403) echo "sh1pt.com $code"; exit 0;; esac + echo "attempt $i: $code"; sleep 10 + done + echo "sh1pt.com never answered"; exit 1 diff --git a/.nixpacks/Dockerfile b/.nixpacks/Dockerfile new file mode 100644 index 00000000..d995722b --- /dev/null +++ b/.nixpacks/Dockerfile @@ -0,0 +1,49 @@ +# dev2 builds this file (cli-tools dev2/dev2-site: compose builds .nixpacks/Dockerfile from the +# repo root). nixpacks' generated Dockerfile cannot build sh1pt.com: it installs the whole +# 555-package workspace on node 18 and never builds the workspace packages the site +# depends on (@profullstack/sh1pt-action-packs, ...). This is sites/sh1pt.com/Dockerfile, +# the one Railway built; keep the two in sync. + +# syntax=docker/dockerfile:1.6 +# Dockerfile for sh1pt.com — built from the monorepo root. +# Reason for existing: Railpack's auto-generated COPY-per-workspace-package +# exceeds BuildKit's mount-options length limit (~344 workspace packages). +# A single bulk COPY sidesteps that. + +FROM node:20-bookworm-slim AS build + +ENV PNPM_HOME=/pnpm +ENV PATH=$PNPM_HOME:$PATH +RUN npm install -g pnpm@9.12.0 + +WORKDIR /app + +COPY . . + +# Replace the workspace file with a minimal one covering only sh1pt-dot-com's +# transitive closure. Otherwise pnpm scans all 555 workspace packages, which +# OOMs the build container. +RUN printf 'packages:\n - sites/sh1pt.com\n - packages/core\n - packages/cli\n - packages/policy\n - packages/openapi\n - packages/actions-fleet-core\n - packages/actions\n - packages/automation/browser\n - packages/secrets/env-updater\n' > pnpm-workspace.yaml + +# Next probes the app env file during build. Railway injects real values at +# runtime, so an empty file keeps container builds deterministic. +RUN touch sites/sh1pt.com/.env + +RUN pnpm --filter sh1pt-dot-com... install --frozen-lockfile=false +RUN pnpm --filter sh1pt-dot-com^... --if-present build +RUN pnpm --filter sh1pt-dot-com build + +FROM node:20-bookworm-slim AS runner + +ENV PNPM_HOME=/pnpm +ENV PATH=$PNPM_HOME:$PATH +ENV NODE_ENV=production +RUN npm install -g pnpm@9.12.0 + +WORKDIR /app + +COPY --from=build --chown=node:node /app /app + +EXPOSE 8080 +USER node +CMD ["sh", "-c", "cd sites/sh1pt.com && exec node node_modules/next/dist/bin/next start -p ${PORT:-8080} -H 0.0.0.0"]