diff --git a/.github/workflows/deploy-auth-api.yml b/.github/workflows/deploy-auth-api.yml index 448eac27de..73fc48ab1e 100644 --- a/.github/workflows/deploy-auth-api.yml +++ b/.github/workflows/deploy-auth-api.yml @@ -2,34 +2,22 @@ name: Deploy Auth API "on": workflow_dispatch: {} +env: + AUTH_API_CLUSTER: shared-cluster + AUTH_API_SERVICE: auth-api + jobs: deploy: - name: Build and push container + name: Deploy latest stable image + environment: shared runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup docker buildx - uses: docker/setup-buildx-action@v1 - with: - install: true - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: - aws-access-key-id: ${{ secrets.AWS_ECS_DEPLOYMENT_USER_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_ECS_DEPLOYMENT_USER_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_ECS_REGION }} - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - - name: Build, tag, and push image to Amazon ECR - run: | - # Build a docker container and - # push it to ECR so that it can - # be deployed to ECS. - docker buildx build --platform=linux/amd64 --output type=docker -f bin/auth-api/Dockerfile . -t si/si-auth-api - docker tag si/si-auth-api:latest ${{ secrets.AWS_ECR_REPOSITORY }}/si/si-auth-api:latest - docker push ${{ secrets.AWS_ECR_REPOSITORY }}/si/si-auth-api:latest + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }} + aws-region: us-east-1 - name: Trigger ECS Deploy run: | - aws ecs update-service --region ${{ secrets.AWS_ECS_REGION }} --cluster ${{ secrets.AWS_ECS_AUTH_API_CLUSTER }} --service ${{ secrets.AWS_ECS_AUTH_API_SERVICE }} --force-new-deployment \ No newline at end of file + aws ecs update-service --cluster ${{ env.AUTH_API_CLUSTER }} --service ${{ env.AUTH_API_SERVICE }} --force-new-deployment diff --git a/bin/auth-api/BUCK b/bin/auth-api/BUCK index 2928123d29..21d7fd3dc9 100644 --- a/bin/auth-api/BUCK +++ b/bin/auth-api/BUCK @@ -4,7 +4,13 @@ load( "export_file", "package_node_modules", "typescript_check", + "docker_image", + "npm_bin", + "typescript_dist", + "typescript_runnable_dist", + "typescript_runnable_dist_bin", ) + load( "@prelude-si//:pnpm.bzl", "pnpm_task_library", @@ -20,6 +26,13 @@ package_node_modules( package_name = "@si/auth-api", ) +filegroup( + name = "prisma", + srcs = glob([ + "prisma/**/*", + ]), +) + filegroup( name = "src", srcs = glob([ @@ -46,6 +59,10 @@ dev_deps_srcs = { "lib/tsconfig": "//lib/tsconfig:src", } +npm_bin( + name = "tsup", +) + eslint( name = "check-lint", directories = ["src", "test"], @@ -71,18 +88,35 @@ eslint( # # -pnpm_task_library( - name = "build", - command = "build", - srcs = glob(["src/**/*", "tsconfig.json"]), - deps = [ - "//:node_modules", - ], - path = "bin/auth-api", - outs = ["dist"], - visibility = ["PUBLIC"], +typescript_dist( + name = "dist", + srcs = [":src"], + tsup = ":tsup", + prod_deps_srcs = prod_deps_srcs, + dev_deps_srcs = dev_deps_srcs, ) +typescript_runnable_dist( + name = "auth-api", +) + +typescript_runnable_dist_bin( + name = "bin", + typescript_runnable_dist = ":auth-api", +) + +# pnpm_task_library( +# name = "build", +# command = "build", +# srcs = glob(["src/**/*", "tsconfig.json"]), +# deps = [ +# "//:node_modules", +# ], +# path = "bin/auth-api", +# outs = ["dist"], +# visibility = ["PUBLIC"], +# ) + pnpm_task_binary( name = "lint-fix", command = "lint:fix", @@ -115,3 +149,12 @@ pnpm_task_binary( ], visibility = ["PUBLIC"], ) + +docker_image( + name = "image", + image_name = "auth-api", + flake_lock = "//:flake.lock", + build_deps = [ + "//bin/auth-api:auth-api", + ] +) diff --git a/bin/auth-api/Dockerfile b/bin/auth-api/Dockerfile index 9c0c3d3c89..c7dfa4579b 100644 --- a/bin/auth-api/Dockerfile +++ b/bin/auth-api/Dockerfile @@ -1,118 +1,35 @@ ARG NODE_VERSION=18.16.0 -# ARG PNPM_VERSION=8.1.1 ARG PACKAGE_PATH=@si/auth-api FROM node:$NODE_VERSION-slim AS base -# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. -# RUN apk add --no-cache libc6-compat -# RUN apk update - -# install pnpm -# RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh - - WORKDIR /app - RUN npm i -g turbo COPY . . RUN turbo prune --scope=@si/auth-api --docker FROM node:$NODE_VERSION-slim AS installer WORKDIR /app -COPY .gitignore .gitignore COPY --from=base /app/out/json/ ./ COPY --from=base /app/out/pnpm-lock.yaml ./app/out/pnpm-workspace.yaml ./ RUN npm i -g pnpm@8.1.1 - -RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store\ - # ↑ By caching the content-addressable store we stop downloading the same packages again and again - PRISMA_SKIP_POSTINSTALL_GENERATE=true\ - pnpm install --filter . --filter @si/auth-api... --frozen-lockfile\ - --unsafe-perm\ - # ↑ Docker runs pnpm as root and then pnpm won't run package scripts unless we pass this arg - | grep -v "cross-device link not permitted\|Falling back to copying packages from store" - -# ↑ This inverted grep match is because using Docker's 'cache' mount type -# causes Docker to place the pnpm content-addressable store on a different virtual drive, -# which prohibits pnpm from symlinking its content to its virtual store (in node_modules/.pnpm), -# and that causes pnpm to fall back on copying the files. And that's fine, -# except pnpm emits a lot of warnings doing that, so here we filter out those warnings. - COPY --from=base /app/out/full/ . -# # Set working directory -# WORKDIR /app -# COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ - -# # pnpm filtering here doesnt work :( -# # TODO: use local cache maybe? -# # RUN pnpm fetch -# COPY lib/tsconfig lib/tsconfig -# COPY lib/eslint-config lib/eslint-config -# COPY lib/ts-lib lib/ts-lib -# COPY bin/auth-api ./bin/auth-api - -# # Calling pnpm fetch first would be better if we had a shared base image and were building multiple images -# # RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store\ -# # pnpm fetch -# # RUN PRISMA_SKIP_POSTINSTALL_GENERATE=1 pnpm install --recursive --offline --frozen-lockfile --unsafe-perm --filter . --filter @si/auth-api... - -# # but we only care about this project, so we'll call install instead -# RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store\ -# # ↑ By caching the content-addressable store we stop downloading the same packages again and again -# PRISMA_SKIP_POSTINSTALL_GENERATE=true\ -# pnpm install --filter . --filter @si/auth-api... --frozen-lockfile\ -# --unsafe-perm\ -# # ↑ Docker runs pnpm as root and then pnpm won't run package scripts unless we pass this arg -# | grep -v "cross-device link not permitted\|Falling back to copying packages from store" - -# # ↑ This inverted grep match is because using Docker's 'cache' mount type -# # causes Docker to place the pnpm content-addressable store on a different virtual drive, -# # which prohibits pnpm from symlinking its content to its virtual store (in node_modules/.pnpm), -# # and that causes pnpm to fall back on copying the files. And that's fine, -# # except pnpm emits a lot of warnings doing that, so here we filter out those warnings. - -# # RUN pnpm install --frozen-lockfile --filter . --filter @si/auth-api... - -# # # Don't run production as root -# # RUN addgroup --system --gid 1001 koa -# # RUN adduser --system --uid 1001 koa -# # USER koa -# # COPY --from=installer /app . - FROM installer as builder WORKDIR /app/bin/auth-api RUN pnpx prisma generate -RUN pnpm run build -RUN echo "strict-peer-dependencies=false" > .npmrc - -RUN PRISMA_SKIP_POSTINSTALL_GENERATE=1 pnpm --prod --filter @si/auth-api deploy pruned -# RUN cp -r src/prisma-client dist -RUN rm -rf pruned/src +RUN pnpm run build \ + && echo "strict-peer-dependencies=false" > .npmrc \ + && PRISMA_SKIP_POSTINSTALL_GENERATE=1 pnpm --prod --filter @si/auth-api deploy pruned \ + && rm -rf pruned/src FROM node:$NODE_VERSION-alpine as runner -RUN PRISMA_SKIP_POSTINSTALL_GENERATE=1 npm i -g pnpm@8.1.1 - +RUN npm i -g pnpm@8.1.1 WORKDIR /app - COPY ./config ./config - -# # ENV NODE_ENV=production COPY --from=builder /app/bin/auth-api/pruned . COPY --from=builder /app/bin/auth-api/dist/src ./dist - -# have to deal with our @si/ts-lib code which exports raw typescript but has been built by this build process -# this is a bit messy, but have tried lots of other solutions to get it running and failed -# move built js files from dist folder into node_modules COPY --from=builder /app/bin/auth-api/dist/node_modules/@si/ts-lib ./node_modules/@si/ts-lib -# update package.json to point to the js files instead of ts -RUN sed -i.bak "s/\.ts/\.js/g" ./node_modules/@si/ts-lib/package.json - -# have to re-run, as it seems the prune call wipes the generated prisma client... -# TODO figure out the best way to avoid this -RUN pnpx prisma generate - -# also prisma adds a huge amount of disk space... -# some discussion and possible things to try here - https://github.com/prisma/prisma/issues/11577 - -# # ENTRYPOINT ["node", "index.js"] +RUN rm -rf ./dist/node_modules \ + && sed -i.bak "s/\.ts/\.js/g" ./node_modules/@si/ts-lib/package.json \ + && pnpx prisma generate CMD pnpm run boot diff --git a/flake.nix b/flake.nix index c6b9213ee2..b2cae192d0 100644 --- a/flake.nix +++ b/flake.nix @@ -198,6 +198,8 @@ in with pkgs; rec { packages = { + auth-api = binDerivation {pkgName = "auth-api";}; + cyclone = binDerivation {pkgName = "cyclone";}; # This one's awful: we don't have a stanalone binary here, we have a