Makefile
Rama main · réplica de lectura del repositorio original.
.PHONY: build_base build_base_test build build_nginx build_branch_app_nginx build_test build_staging build_production clean clean_local pull stop
NEW_BASE_REPO ?= $(ECR_REGISTRY)/gumroad/web_base
NEW_WEB_REPO ?= $(ECR_REGISTRY)/gumroad/web
NEW_WEB_BASE_TEST_REPO ?= $(ECR_REGISTRY)/gumroad/web_base_test
NGINX_REPO ?= $(ECR_REGISTRY)/gumroad/web_nginx
NGINX_TAG ?= latest
BRANCH_APP_NGINX_REPO ?= $(ECR_REGISTRY)/gumroad/branch_app_nginx
BRANCH_APP_NGINX_TAG ?= latest
WEB_COMMAND ?= "/usr/local/bin/gosu app docker/web/server.sh"
NEW_WEB_TAG ?= $(shell git rev-parse --short=12 HEAD)
COMPOSE_PROJECT_NAME ?= web
RUBY_VERSION := $(shell cat .ruby-version)
# Debian 12. An EOL Debian stops having its security metadata re-signed, which
# breaks `apt-get update` in every image built on it -- bump before June 2028.
WEB_BASE_DOCKERFILE_FROM ?= ruby:$(RUBY_VERSION)-slim-bookworm
DOCKER_CMD ?= docker
# Overridable so CI can swap in `docker buildx build --load` (BuildKit) while
# local/fallback builds keep the classic builder. --compress lives here because
# buildx does not support the flag.
DOCKER_BUILD ?= $(DOCKER_CMD) build --compress
# Per-target cache flags. Defaults reproduce the pre-BuildKit behavior exactly;
# CI overrides them with --cache-from/--cache-to type=registry against ECR.
BASE_CACHE_OPTS ?= --cache-from $(NEW_BASE_REPO):latest
WEB_CACHE_OPTS ?= --cache-from $(NEW_BASE_REPO):$(shell ./docker/base/generate_tag_for_web_base.sh) --cache-from $(NEW_WEB_REPO):web-$(NEW_WEB_TAG)
# How the built web image leaves the builder, and what runs after. The defaults
# reproduce the classic flow: build into the local Docker engine tagged
# :latest, then add the commit-specific web-<sha> tag (the caller pushes it).
# CI's BuildKit path overrides these to push the web-<sha> tag straight from
# the builder to ECR, skipping the slow export back into the local engine.
WEB_OUTPUT_OPTS ?= -t $(NEW_WEB_REPO):latest
WEB_POST_BUILD ?= $(DOCKER_CMD) tag $(NEW_WEB_REPO):latest $(NEW_WEB_REPO):web-$(NEW_WEB_TAG)
NGINX_CACHE_OPTS ?=
BRANCH_APP_NGINX_CACHE_OPTS ?=
DOCKER_COMPOSE_CMD ?= docker compose
AWS_CLI_DOCKER_IMAGE ?= garland/aws-cli-docker
PUSH_ASSETS ?= false
LOCAL_DETACHED ?= false
LOCAL_DOCKER_COMPOSE_CONFIG = docker-compose-local.yml
build_base:
: $${BUNDLE_GEMS__CONTRIBSYS__COM?"Need to set BUNDLE_GEMS__CONTRIBSYS__COM for sidekiq-pro"}
rm -f docker/base/Gemfile* docker/base/.ruby-version
cp Gemfile* .ruby-version docker/base
cd docker/base \
&& $(DOCKER_BUILD) -t $(NEW_BASE_REPO):latest \
--build-arg BUNDLE_GEMS__CONTRIBSYS__COM \
--build-arg WEB_BASE_DOCKERFILE_FROM=$(WEB_BASE_DOCKERFILE_FROM) \
$(BASE_CACHE_OPTS) \
. \
&& ./generate_tag_for_web_base.sh | xargs -I{} $(DOCKER_CMD) tag $(NEW_BASE_REPO):latest $(NEW_BASE_REPO):{} \
&& rm -f Gemfile* .ruby-version
build_base_test:
rm -f docker/base/Gemfile* docker/base/.ruby-version
cp Gemfile* .ruby-version docker/base
cd docker/base \
&& WEB_BASE_DOCKERFILE_FROM=$(NEW_BASE_REPO):$(shell ./docker/base/generate_tag_for_web_base.sh) \
$(DOCKER_CMD) build -t $(NEW_BASE_REPO)_test:latest \
--cache-from $(NEW_WEB_BASE_TEST_REPO):latest \
--build-arg WEB_BASE_DOCKERFILE_FROM \
--file Dockerfile.test \
--compress . \
&& ./generate_tag_for_web_base_test.sh | xargs -I{} $(DOCKER_CMD) tag $(NEW_BASE_REPO)_test:latest $(NEW_WEB_BASE_TEST_REPO):{}
build:
: $${BUNDLE_GEMS__CONTRIBSYS__COM?"Need to set BUNDLE_GEMS__CONTRIBSYS__COM for sidekiq-pro"}
echo $(NEW_WEB_TAG) > revision
WEB_DOCKERFILE_FROM=$(NEW_BASE_REPO):$(shell ./docker/base/generate_tag_for_web_base.sh) \
$(DOCKER_BUILD) $(WEB_OUTPUT_OPTS) \
--build-arg BUNDLE_GEMS__CONTRIBSYS__COM \
$(WEB_CACHE_OPTS) \
--build-arg WEB_DOCKERFILE_FROM \
--file docker/web/Dockerfile \
.
$(WEB_POST_BUILD)
build_nginx:
$(DOCKER_BUILD) -t $(NGINX_REPO):$(NGINX_TAG) \
$(NGINX_CACHE_OPTS) \
--file docker/nginx/Dockerfile \
.
build_branch_app_nginx:
$(DOCKER_BUILD) -t $(BRANCH_APP_NGINX_REPO):$(BRANCH_APP_NGINX_TAG) \
$(BRANCH_APP_NGINX_CACHE_OPTS) \
--file docker/branch_app_nginx/Dockerfile \
.
build_test:
WEB_DOCKERFILE_FROM=$(NEW_BASE_REPO):$(shell ./docker/base/generate_tag_for_web_base.sh) \
WEB_BASE_TEST_DOCKERFILE_FROM=$(NEW_BASE_REPO)_test:$(shell ./docker/base/generate_tag_for_web_base_test.sh) \
$(DOCKER_CMD) build -t $(NEW_WEB_REPO):test-$(NEW_WEB_TAG) \
--cache-from $(NEW_BASE_REPO):$(shell ./docker/base/generate_tag_for_web_base.sh) \
--cache-from $(NEW_WEB_BASE_TEST_REPO):$(shell ./docker/base/generate_tag_for_web_base_test.sh) \
--cache-from $(NEW_WEB_REPO):test-$(NEW_WEB_TAG) \
--cache-from $(NEW_WEB_REPO):test-cache \
--build-arg WEB_DOCKERFILE_FROM \
--build-arg WEB_BASE_TEST_DOCKERFILE_FROM \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--file docker/web/Dockerfile.test \
--compress .
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml up -d db_test redis elasticsearch
$(DOCKER_CMD) run --network $(COMPOSE_PROJECT_NAME)_default \
--entrypoint="" \
$(NEW_WEB_REPO):test-$(NEW_WEB_TAG) \
docker/ci/wait_on_connection.sh db_test 3306
$(DOCKER_CMD) run --network $(COMPOSE_PROJECT_NAME)_default \
--entrypoint="" \
--shm-size="2g" \
--memory-swappiness="0" \
-e RAILS_ENV="test" \
-e RAILS_MASTER_KEY=$(RAILS_MASTER_KEY) \
-e BRANCH_CACHE_UPLOAD_ENABLED=$(BRANCH_CACHE_UPLOAD_ENABLED) \
-e BRANCH_CACHE_RESTORE_ENABLED=$(BRANCH_CACHE_RESTORE_ENABLED) \
-e CACHE_TAR_FILE=$(CACHE_TAR_FILE) \
--label routes_compiled=true \
--name worker_$(COMPOSE_PROJECT_NAME) \
-v $${PWD}:/mnt/host \
$(NEW_WEB_REPO):test-$(NEW_WEB_TAG) \
bash -c "su -c \"[[ -e /mnt/host/$$CACHE_TAR_FILE ]] && tar -xf /mnt/host/$$CACHE_TAR_FILE -C . || true; npm run setup && bundle exec rake db:setup assets:precompile --trace\" app; exit_status=$$?; [[ $$BRANCH_CACHE_UPLOAD_ENABLED == 'true' ]] && tar -cf /mnt/host/$$CACHE_TAR_FILE node_modules public/assets public/js public/vite-test tmp/cache/assets || true; [[ $$BRANCH_CACHE_RESTORE_ENABLED == 'true' ]] && rm -rf node_modules public/assets public/pages-tailwind-manifest.json tmp/cache/assets || true; exit $$exit_status"
$(DOCKER_CMD) ps -lq --filter='label=routes_compiled=true' --filter='exited=0' --filter='name=worker_$(COMPOSE_PROJECT_NAME)' | xargs -I{} $(DOCKER_CMD) commit {} $(NEW_WEB_REPO):test-$(NEW_WEB_TAG)
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml down
define remove_spec_folder
rm -rf spec/
endef
build_staging:
: $${GUM_AWS_ACCESS_KEY_ID?"Need to set GUM_AWS_ACCESS_KEY_ID"}
: $${GUM_AWS_SECRET_ACCESS_KEY?"Need to set GUM_AWS_SECRET_ACCESS_KEY"}
: $${RAILS_STAGING_MASTER_KEY?"Need to set RAILS_STAGING_MASTER_KEY"}
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml up -d db_test memcached redis
$(DOCKER_CMD) run \
--name $(COMPOSE_PROJECT_NAME)_staging-assets \
--network $(COMPOSE_PROJECT_NAME)_default \
--entrypoint="" \
--shm-size="2g" \
--memory-swappiness="0" \
-e RAILS_ENV="staging" \
-e RACK_ENV="staging" \
-e DATABASE_HOST="db_test" \
-e DATABASE_NAME="gumroad_test" \
-e DATABASE_USERNAME="root" \
-e DATABASE_PASSWORD="password" \
-e DEVISE_SECRET_KEY="sample_secret_key" \
-e RAILS_MASTER_KEY=$(RAILS_STAGING_MASTER_KEY) \
-e BUILDKITE_BRANCH=$(BUILDKITE_BRANCH) \
-e REVISION=$(NEW_WEB_TAG) \
--label assets_compiled=true \
$(NEW_WEB_REPO):web-$(NEW_WEB_TAG) \
gosu app bash -c "docker/web/compile_assets.sh && $(call remove_spec_folder)"
$(DOCKER_CMD) ps -lq --filter='name=$(COMPOSE_PROJECT_NAME)_staging-assets' --filter='label=assets_compiled=true' --filter='exited=0' | xargs -I{} $(DOCKER_CMD) commit {} $(NEW_WEB_REPO):staging-$(NEW_WEB_TAG)
ifeq ($(PUSH_ASSETS),true)
set -e; \
container_id=$$($(DOCKER_CMD) run -d --entrypoint="bash" --volume /app $(NEW_WEB_REPO):staging-$(NEW_WEB_TAG)); \
trap "$(DOCKER_CMD) rm -f $$container_id >/dev/null 2>&1 || true" EXIT; \
$(DOCKER_CMD) run \
-e AWS_ACCESS_KEY_ID=$$GUM_AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY=$$GUM_AWS_SECRET_ACCESS_KEY \
-e ASSETS_S3_BUCKET=gumroad-staging-assets \
--volumes-from $$container_id \
$(AWS_CLI_DOCKER_IMAGE) \
sh /app/docker/web/push_assets_to_s3.sh
endif
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml down
build_production:
: $${GUM_AWS_ACCESS_KEY_ID?"Need to set GUM_AWS_ACCESS_KEY_ID"}
: $${GUM_AWS_SECRET_ACCESS_KEY?"Need to set GUM_AWS_SECRET_ACCESS_KEY"}
: $${RAILS_PRODUCTION_MASTER_KEY?"Need to set RAILS_PRODUCTION_MASTER_KEY"}
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml up -d db_test memcached redis
$(DOCKER_CMD) run \
--name $(COMPOSE_PROJECT_NAME)_production-assets \
--network $(COMPOSE_PROJECT_NAME)_default \
--entrypoint="" \
--shm-size="2g" \
--memory-swappiness="0" \
-e RAILS_ENV="production" \
-e RACK_ENV="production" \
-e DATABASE_HOST="db_test" \
-e DATABASE_NAME="gumroad_test" \
-e DATABASE_USERNAME="root" \
-e DATABASE_PASSWORD="password" \
-e RAILS_MASTER_KEY=$$RAILS_PRODUCTION_MASTER_KEY \
-e DEVISE_SECRET_KEY="sample_secret_key" \
-e BUILDKITE_BRANCH=$(BUILDKITE_BRANCH) \
-e REVISION=$(NEW_WEB_TAG) \
--label assets_compiled=true \
$(if $(NODE_MODULES_CACHE_DIR),-v $(NODE_MODULES_CACHE_DIR):/node-modules-cache) \
$(if $(PAGES_TAILWIND_CACHE_DIR),-v $(PAGES_TAILWIND_CACHE_DIR):/pages-tailwind-cache) \
$(NEW_WEB_REPO):web-$(NEW_WEB_TAG) \
gosu app bash -c "docker/web/compile_assets.sh && $(call remove_spec_folder)"
$(DOCKER_CMD) ps -lq --filter='name=$(COMPOSE_PROJECT_NAME)_production-assets' --filter='label=assets_compiled=true' --filter='exited=0' | xargs -I{} $(DOCKER_CMD) commit {} $(NEW_WEB_REPO):production-$(NEW_WEB_TAG)
ifeq ($(PUSH_ASSETS),true)
set -e; \
container_id=$$($(DOCKER_CMD) run -d --entrypoint="bash" --volume /app $(NEW_WEB_REPO):production-$(NEW_WEB_TAG)); \
trap "$(DOCKER_CMD) rm -f $$container_id >/dev/null 2>&1 || true" EXIT; \
$(DOCKER_CMD) run \
-e AWS_ACCESS_KEY_ID=$$GUM_AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY=$$GUM_AWS_SECRET_ACCESS_KEY \
-e ASSETS_S3_BUCKET=gumroad-production-assets \
--volumes-from $$container_id \
$(AWS_CLI_DOCKER_IMAGE) \
sh /app/docker/web/push_assets_to_s3.sh
endif
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml down
clean:
rm -rf docker/tmp/
clean_local:
rm -f revision web_base_sha
pull:
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml pull db_test elasticsearch
local:
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/$(LOCAL_DOCKER_COMPOSE_CONFIG) up $(if $(filter true,$(LOCAL_DETACHED)),-d)
stop_local:
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/$(LOCAL_DOCKER_COMPOSE_CONFIG) down
stop:
COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) \
$(DOCKER_COMPOSE_CMD) -f docker/docker-compose-test-and-ci.yml down
.PHONY: shortest
shortest:
@./scripts/shortest.sh || true