diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6a0d87ef --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +node_modules +.env* diff --git a/.env.sample b/.env.sample new file mode 100644 index 00000000..1e593430 --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +SQL_GENERATE_URL=postgres://sql-url diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 999f0788..0eaf48df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,11 +97,3 @@ jobs: - uses: oven-sh/setup-bun@v2 - run: bun prepare:deploy:web - run: test `ls web/.next | wc -l` != 0 - - deploy-test-server: - name: Deploy Test (server) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - - run: bun prepare:deploy:server diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..1cd25f63 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,17 @@ +name: Deploy +on: + push: + branches: + - main + +jobs: + deploy: + name: Deploy Server to Fly.io + runs-on: ubuntu-latest + env: + SQL_GENERATE_URL: ${{ secrets.DATABASE_URL_FOR_PRISMA_SQL_GENERATION }} + + steps: + - uses: actions/checkout@v4 + - uses: superfly/flyctl-actions/setup-flyctl@master + - run: flyctl deploy --build-arg SQL_GENERATE_URL=$SQL_GENERATE_URL --access-token "${{ secrets.FLY_DEPLOY_TOKEN }}" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..80b12fec --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# syntax = docker/dockerfile:1 + +ARG BUN_VERSION=1.2.2 +FROM oven/bun:${BUN_VERSION} AS base +LABEL fly_launch_runtime="Bun/Prisma" +ENV NODE_ENV="production" + +# Throw-away build stage to reduce size of final image +FROM base AS build + +WORKDIR /build +ARG SQL_GENERATE_URL +RUN test -n "${SQL_GENERATE_URL}" +ENV DATABASE_URL=$SQL_GENERATE_URL +ENV DIRECT_URL=$SQL_GENERATE_URL +COPY . . +RUN --mount=type=cache,target=~/.bun/install bun install --frozen-lockfile --ignore-scripts +RUN cd server; bun prisma generate --sql +RUN cd server; bun run :build + + +# Final stage for app image +FROM base AS runner +WORKDIR /srv + +# Copy built application +COPY --from=build /build/server/target/index.js /srv/index.js +COPY --from=build /build/node_modules/.prisma/client /node_modules/.prisma/client +COPY --from=build /build/node_modules/@img /node_modules/@img + +# Start the server by default, this can be overwritten at runtime +EXPOSE 3000 +CMD [ "bun", "run", "./index.js" ] diff --git a/README.md b/README.md index 598d7edb..d3b8945e 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,6 @@ make prepare-deploy-web` server: ```sh -make prepare-deploy-server -make deploy-server +# prisma がビルド時に DATABASE_URL を要求するため、 root に .env を作って、 .env.sample に従って埋めよう。 +bun deploy:server ``` diff --git a/flake.nix b/flake.nix index c5786b20..79e4ae47 100644 --- a/flake.nix +++ b/flake.nix @@ -39,6 +39,7 @@ packages = (with pkgs; [ nix # HACK: to fix the side effect of the hack below, installing two instances of nix + flyctl gnumake nodejs biome diff --git a/fly.toml b/fly.toml new file mode 100644 index 00000000..0c62208c --- /dev/null +++ b/fly.toml @@ -0,0 +1,24 @@ +# fly.toml app configuration file generated for coursemate on 2025-03-06T14:33:10+09:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = 'coursemate' +primary_region = 'nrt' + +[build] + +[deploy] + +[http_service] +internal_port = 3000 +force_https = true +auto_stop_machines = 'stop' +auto_start_machines = true +min_machines_running = 0 +processes = ['app'] + +[[vm]] +memory = '512mb' +cpu_kind = 'shared' +cpus = 1 diff --git a/package.json b/package.json index fbe2eb32..53a312ad 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,10 @@ "watch:server": "cd server; bun run dev", "seed": "cd server; bun prisma db seed", "prepare:deploy:web": "bun install && bun run build:web", - "prepare:deploy:server": "bun install", "deploy:web": "cd web; bun run start --port $PORT", - "deploy:server": "cd server; bun run src/index.ts", + "deploy:server": "bun run --env-file=.env :deploy:server", + ":deploy:server": "fly deploy --build-arg SQL_GENERATE_URL=$SQL_GENERATE_URL", + "docker:server": "docker build . --build-arg SQL_GENERATE_URL=$SQL_GENERATE_URL", "dev-db": "make dev-db", "test": "make test", "spell": "bunx cspell --quiet ." diff --git a/server/.gitignore b/server/.gitignore index c0bced27..f7361e03 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -2,8 +2,6 @@ node_modules # WARNING: DELETE THIS IF YOU FIND THIS .env - .env.dev -# deprecated, delete /dist if you have one -/dist + /target diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index 99b960c8..00000000 --- a/server/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM oven/bun:latest -WORKDIR /coursemate/dev/server - -COPY package.json package-lock.json ./ -RUN npm ci - -COPY ./prisma ./ -RUN npx prisma generate - -COPY . . - -RUN npm run build -CMD npx prisma db push && npm run serve diff --git a/server/package.json b/server/package.json index 32d9a02d..e23f0407 100644 --- a/server/package.json +++ b/server/package.json @@ -6,8 +6,10 @@ "scripts": { "prepare": "bun --env-file=./.env.dev prisma generate --sql || (echo 'please set DATABASE_URL in server/.env.dev' && exit 1)", "dev": "bun --watch src/index.ts", - "build": "tsc", - "serve": "bun target/main.js" + "check": "tsc", + "clean": "rm target -r || true", + "build": "bun clean && bun check && bun run :build", + ":build": "bun build ./src/index.ts --target bun --outfile target/index.js --minify" }, "prisma": { "seed": "bun src/seeds/seed-test.ts" diff --git a/server/prisma.nix b/server/prisma.nix index bdb062f5..63cb161f 100644 --- a/server/prisma.nix +++ b/server/prisma.nix @@ -6,13 +6,13 @@ (prisma-utils.lib.prisma-factory { inherit pkgs; - prisma-fmt-hash = "sha256-atD5GZfmeU86mF1V6flAshxg4fFR2ews7EwaJWZZzbc="; - query-engine-hash = "sha256-8FTZaKmQCf9lrDQvkF5yWPeZ7TSVfFjTbjdbWWEHgq4="; - libquery-engine-hash = "sha256-USIdaum87ekGY6F6DaL/tKH0BAZvHBDK7zjmCLo//kM="; - schema-engine-hash = "sha256-k5MkxXViEqojbkkcW/4iBFNdfhb9PlMEF1M2dyhfOok="; + prisma-fmt-hash = "sha256-iZuomC/KaLF0fQy6RVHwk2qq4DRaG3xj+sWmtLofiMU="; + query-engine-hash = "sha256-Pl/YpYu326qqpbVfczM5RxB8iWXZlewG9vToqzSPIQo="; + libquery-engine-hash = "sha256-ETwMIJMjMgZmjH6QGD7GVwYYlyx9mo2ydEeunFViCjQ="; + schema-engine-hash = "sha256-rzzzPHOpUM3GJvkhU08lQ7rNspdq3RKxMRRW9YZtvhU="; }) .fromBunLock - ./bun.lock; + ../bun.lock; inherit (prisma) package; in { inherit (prisma) shellHook; diff --git a/server/tsconfig.json b/server/tsconfig.json index ac133f64..20df3ed0 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "target": "es2016", + "noEmit": true, "module": "commonjs", "rootDir": "./src", "outDir": "./target",