Skip to content

fix(members): make backfill remote state visible and stop-safe #1693

fix(members): make backfill remote state visible and stop-safe

fix(members): make backfill remote state visible and stop-safe #1693

Workflow file for this run

name: CI
# Enable Buildkit and let compose use it to speed up image building
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
on:
pull_request:
branches: ['main', 'dev']
paths-ignore: ['docs/**']
push:
branches: ['main', 'dev']
paths-ignore: ['docs/**']
permissions:
id-token: write
contents: write
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
linter:
# Skip the whole workflow for bump: commits — the bump only mutates
# version files we already linted/tested in the run that produced
# the bump. head_commit is unset on pull_request, so PR validation
# is unaffected.
if: github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'bump:')
runs-on: ubuntu-24.04-arm
steps:
- name: Checkout Code Repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version-file: '.python-version'
- name: Run pre-commit
uses: pre-commit/action@v3.0.1
test:
if: github.event_name != 'push' || !startsWith(github.event.head_commit.message, 'bump:')
runs-on: ubuntu-24.04-arm
env:
AWS_REGION: us-east-1
steps:
- name: Checkout Code Repository
uses: actions/checkout@v6
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::755997884632:role/github-actions-kcprofiles
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build the Stack
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: docker compose -f docker-compose.github.yml build
- name: Check DB Migrations
id: check_migrations
run: docker compose -f docker-compose.github.yml run --rm django uv run python manage.py makemigrations --check
- name: Show postgres logs on failure
if: failure() && steps.check_migrations.outcome == 'failure'
run: docker compose -f docker-compose.github.yml logs postgres
- name: Run DB Migrations
run: docker compose -f docker-compose.github.yml run --rm django uv run python manage.py migrate
- name: Run Django Tests
run: docker compose -f docker-compose.github.yml run --rm django uv run coverage run manage.py test
- name: Run Cron/Monitor Tests (pytest)
run: docker compose -f docker-compose.github.yml run --rm django uv run python -m pytest knowledge_commons_profiles/cron/tests/ -v
- name: Generate lcov
run: docker compose -f docker-compose.github.yml run --rm django uv run coverage lcov
- name: Create coverage stats
if: github.actor != 'dependabot[bot]'
uses: gaelgirodon/ci-badges-action@v1
with:
gist-id: 0ed9af78da10972471ef6bf61524ba5e
token: ${{ secrets.GIST_TOKEN }}
- name: Tear down the Stack
run: docker compose -f docker-compose.github.yml down
release-main:
# Bumps the version with commitizen, then builds, pushes images, and
# deploys — all in one workflow run so every main release is deployed
# at exactly the version it claims. The bump commit is only pushed
# back to main after the ECR push succeeds, so a failed build never
# leaves a stranded bump on the branch. Skipped on bump: commits
# (already deployed by the run that created them) to avoid recursion.
name: Release (main)
runs-on: ubuntu-24.04-arm
needs: [linter, test]
if: github.event_name == 'push' && github.ref_name == 'main' && !startsWith(github.event.head_commit.message, 'bump:')
environment: production
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: kcprofiles
ECR_REPOSITORY_TRAEFIK: kcprofiles-traefik
ECR_REPOSITORY_MONITOR: kcprofiles-monitor
ECR_REPOSITORY_IDMS: kcprofiles-idms
ECS_CLUSTER: kcprofiles
ECS_SERVICE: kcprofiles-blue
AUTOSCALE_GROUP: Infra-ECS-Cluster-kcprofiles-ee645084-ECSAutoScalingGroup-v3MrRnH7laIx
COMPOSE_FILE: docker-compose.production.yml
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
ssh-key: ${{ secrets.COMMIT_KEY }}
- name: Bump version with commitizen
id: bump
env:
COMMITIZEN_VERSION: "4.16.2"
run: |
python3 -m pip install --user "commitizen==${COMMITIZEN_VERSION}"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
PRE_SHA=$(git rev-parse HEAD)
set +e
"$HOME/.local/bin/cz" bump --yes
EXIT_CODE=$?
set -e
POST_SHA=$(git rev-parse HEAD)
if [ "$EXIT_CODE" = "0" ] && [ "$PRE_SHA" != "$POST_SHA" ]; then
echo "bumped=true" >> $GITHUB_OUTPUT
elif [ "$EXIT_CODE" = "0" ] || [ "$EXIT_CODE" = "21" ]; then
# cz returned 21 (NoCommitsFoundError) or succeeded without
# changing HEAD: nothing semantic to bump, deploy at the
# existing version.
echo "bumped=false" >> $GITHUB_OUTPUT
else
echo "cz bump failed unexpectedly with exit code $EXIT_CODE" >&2
exit "$EXIT_CODE"
fi
- name: Identify bump commit
id: bump_commit
run: |
BUMP_SHA=$(git rev-parse HEAD)
echo "sha=$BUMP_SHA" >> $GITHUB_OUTPUT
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::755997884632:role/github-actions-kcprofiles
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Extract project version
id: project_version
run: |
VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
SHORT_SHA=$(git rev-parse --short=7 HEAD)
echo "version=v${VERSION}" >> $GITHUB_OUTPUT
echo "build=v${VERSION}-${SHORT_SHA}" >> $GITHUB_OUTPUT
- name: Build, tag, and push images to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ steps.bump_commit.outputs.sha }}
VERSION_TAG: ${{ steps.project_version.outputs.version }}
BUILD_TAG: ${{ steps.project_version.outputs.build }}
run: |
docker compose -f $COMPOSE_FILE build
# Re-tag the freshly built images with the meaningful version-anchored
# names used for emergency rollback. BUILD_TAG (vX.Y.Z-<sha7>) is
# always unique; VERSION_TAG (vX.Y.Z) tracks the latest build of a
# given release on main.
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY:$VERSION_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$VERSION_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$VERSION_TAG
# Push Django image
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$VERSION_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
# Push Traefik image
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$VERSION_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:latest
# Push IDMS image
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$VERSION_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:latest
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Build, tag, and push monitor image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ steps.bump_commit.outputs.sha }}
VERSION_TAG: ${{ steps.project_version.outputs.version }}
BUILD_TAG: ${{ steps.project_version.outputs.build }}
run: |
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$VERSION_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:$VERSION_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_MONITOR:latest
- name: Push bump commit and tag to main
# Only happens after every ECR push above has succeeded; a failure
# in the build leaves no stranded bump on the branch. Skipped when
# commitizen had nothing semantic to bump.
if: steps.bump.outputs.bumped == 'true'
run: |
git push origin main --tags
- name: Force deployment
continue-on-error: true
run: |
aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment
aws autoscaling start-instance-refresh --auto-scaling-group-name $AUTOSCALE_GROUP --region $AWS_REGION --preferences '{"SkipMatching": false}'
- name: Set a Sentry release
uses: getsentry/action-release@v3
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
with:
environment: production
ignore_missing: true
deploy-dev:
name: Deploy (dev)
runs-on: ubuntu-24.04-arm
needs: [linter, test]
if: github.event_name == 'push' && github.ref_name == 'dev'
environment: dev
env:
AWS_REGION: us-east-1
ECR_REPOSITORY: kcprofiles-dev
ECR_REPOSITORY_TRAEFIK: kcprofiles-traefik-dev
ECR_REPOSITORY_IDMS: kcprofiles-idms-dev
ECS_CLUSTER: kcprofiles-dev-2
ECS_SERVICE: kcprofiles-dev
AUTOSCALE_GROUP: Infra-ECS-Cluster-kcprofiles-dev-2-f89c2350-ECSAutoScalingGroup-zUYaGlEf1GWi
COMPOSE_FILE: docker-compose.dev.yml
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6
with:
role-to-assume: arn:aws:iam::755997884632:role/github-actions-kcprofiles
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Extract project version
id: project_version
run: |
VERSION=$(python3 -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
SHORT_SHA="${GITHUB_SHA::7}"
echo "build=v${VERSION}-${SHORT_SHA}" >> $GITHUB_OUTPUT
- name: Build, tag, and push images to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
BUILD_TAG: ${{ steps.project_version.outputs.build }}
run: |
docker compose -f $COMPOSE_FILE build
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$BUILD_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$IMAGE_TAG \
$ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_TRAEFIK:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:$BUILD_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY_IDMS:latest
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Force deployment
continue-on-error: true
run: |
aws ecs update-service --cluster $ECS_CLUSTER --service $ECS_SERVICE --force-new-deployment
aws autoscaling start-instance-refresh --auto-scaling-group-name $AUTOSCALE_GROUP --region $AWS_REGION --preferences '{"SkipMatching": false}'
- name: Set a Sentry release
uses: getsentry/action-release@v3
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
with:
environment: dev
ignore_missing: true