Deploy: stop shipping 90 MB of node_modules the build throws away
CI / checks (push) Successful in 2m46s Details

The S3 artifact is 32.9 MiB compressed. Every other project's zip in that
bucket is under 1 MiB. The difference is frontend/node_modules, which is
committed to this repo and so was swept into every upload.

Earlier I left it in because nothing in the repo says what consumes the
bucket object, and if that side ran the app without installing dependencies,
dropping it would have broken the deploy. That is now answered rather than
assumed. Traced on the instance:

  CodeDeploy extracts to /opt/codedeploy-extracted-5, the AfterInstall hook
  copies the tree to /home/ec2-user/utopia-ai-hr-ats-portal-deployment-group,
  then runs `docker compose --env-file ./backend/.env up -d --build`.

Eleven containers come up and the only Node one is hrms-frontend, built from
frontend/Dockerfile, which does `npm ci` against the lockfile. On top of that
frontend/.dockerignore excludes node_modules/ from the build context outright,
so even the copy that arrived could not have been read. It was carried across
the wire on every merge to main and then discarded unread.

The exclusion patterns were verified rather than trusted: zip -r with
-x on a synthetic tree in a temp dir on the box, since zip is not available
locally. That run also confirmed the previous commit's other fix — the
original `-x ".gitignore/*"` really did fail to match the file, and
`-x ".gitignore"` matches it.

Not done here, deliberately: node_modules is still tracked in git, which is
why it was in the artifact in the first place. Untracking it deletes 5,230
files from every other contributor's working tree on their next pull, across
thirteen active branches, and needs a heads-up rather than a surprise.

Two things found while reading the deploy script, neither touched:

  - It copies with `cp -r` and never deletes, so a file removed from the repo
    survives on the server indefinitely. Switching to a delete-on-sync would
    risk backend/.env, which the script deliberately preserves.
  - It re-downloads the latest docker compose and buildx from GitHub on every
    single deploy, unpinned, as root.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
pull/73/head^2
Talha Ahmed 2026-09-03 18:39:43 +05:00
parent 3b5ba425e8
commit 0113509fa1
1 changed files with 13 additions and 6 deletions

View File

@ -47,12 +47,18 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
# NOTE: this zip still contains frontend/node_modules, roughly 90 MB and
# the bulk of the artifact. It is left in deliberately. Nothing in this
# repo says what unpacks the zip on the other side — there is no appspec
# file and no deploy script here — so if that side runs the app without
# installing dependencies, dropping node_modules would break the deploy.
# Confirm what consumes the bucket object, then add -x "frontend/node_modules/*".
# frontend/node_modules is excluded, and that is safe because of what
# happens to this object downstream. CodeDeploy pulls it, extracts to
# /opt/codedeploy-extracted-5, copies the tree to
# /home/ec2-user/utopia-ai-hr-ats-portal-deployment-group and runs
# `docker compose --env-file ./backend/.env up -d --build`. The only Node
# service is the frontend, whose image does `npm ci` from the lockfile,
# and frontend/.dockerignore excludes node_modules/ from the build context
# outright. So the committed tree was carried into every artifact and then
# thrown away unread. It was 90 MB of a 33 MB compressed upload.
#
# node_modules is still tracked in git, which is the reason it was here at
# all. Untracking it is a separate change and affects other branches.
- name: Archive project
run: |
apt-get update -y
@ -61,6 +67,7 @@ jobs:
-x ".git/*" \
-x ".gitea/*" \
-x ".gitignore" \
-x "frontend/node_modules/*" \
-x "*.DS_Store"
- name: Install AWS CLI