FossilRepo

CI/CD: deploy to dev on push, promote to prd on version tag - deploy.yaml: push to main → build, tag latest+SHA, deploy to dev ECS - promote.yaml: push vX.X.X tag → retag latest as stable+version, deploy to prd ECS - Single ECR repo 'fossilrepo', tag strategy: latest (dev), stable+vX.X.X (prd)

lmata 2026-04-07 04:01 trunk
Commit 6f6482c20ed028f29bb8012581609b4cd273d8e1785dd8151a03c2a60b2b7fb6
--- .github/workflows/deploy.yaml
+++ .github/workflows/deploy.yaml
@@ -8,21 +8,19 @@
88
- 'mkdocs.yml'
99
- '*.md'
1010
1111
env:
1212
AWS_REGION: us-west-2
13
- ECR_REPO: dev-fossilrepo-app
13
+ ECR_REPO: fossilrepo
1414
ECS_CLUSTER: dev-fossilrepo
1515
ECS_SERVICE: dev-fossilrepo-app
1616
TASK_FAMILY: dev-fossilrepo-app
1717
1818
jobs:
19
- # ── Gate: CI must pass before deploying ──────────────────────────────────
2019
ci:
2120
uses: ./.github/workflows/ci.yaml
2221
23
- # ── Build + Push + Deploy ────────────────────────────────────────────────
2422
deploy:
2523
needs: [ci]
2624
runs-on: ubuntu-latest
2725
permissions:
2826
id-token: write
@@ -55,31 +53,27 @@
5553
- name: Deploy to ECS
5654
env:
5755
ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
5856
IMAGE_TAG: ${{ github.sha }}
5957
run: |
60
- # Get current task definition
6158
TASK_DEF=$(aws ecs describe-task-definition \
6259
--task-definition $TASK_FAMILY \
6360
--query 'taskDefinition' \
6461
--output json)
6562
66
- # Update image in container definitions, strip read-only fields
6763
NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
6864
--arg IMAGE "$ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG" \
6965
'.containerDefinitions[0].image = $IMAGE |
7066
del(.taskDefinitionArn, .revision, .status,
7167
.requiresAttributes, .compatibilities,
7268
.registeredAt, .registeredBy, .deregisteredAt)')
7369
74
- # Register new task definition
7570
NEW_TASK_ARN=$(aws ecs register-task-definition \
7671
--cli-input-json "$NEW_TASK_DEF" \
7772
--query 'taskDefinition.taskDefinitionArn' \
7873
--output text)
7974
80
- # Update service with new task definition
8175
aws ecs update-service \
8276
--cluster $ECS_CLUSTER \
8377
--service $ECS_SERVICE \
8478
--task-definition "$NEW_TASK_ARN" \
8579
--force-new-deployment
8680
8781
ADDED .github/workflows/promote.yaml
--- .github/workflows/deploy.yaml
+++ .github/workflows/deploy.yaml
@@ -8,21 +8,19 @@
8 - 'mkdocs.yml'
9 - '*.md'
10
11 env:
12 AWS_REGION: us-west-2
13 ECR_REPO: dev-fossilrepo-app
14 ECS_CLUSTER: dev-fossilrepo
15 ECS_SERVICE: dev-fossilrepo-app
16 TASK_FAMILY: dev-fossilrepo-app
17
18 jobs:
19 # ── Gate: CI must pass before deploying ──────────────────────────────────
20 ci:
21 uses: ./.github/workflows/ci.yaml
22
23 # ── Build + Push + Deploy ────────────────────────────────────────────────
24 deploy:
25 needs: [ci]
26 runs-on: ubuntu-latest
27 permissions:
28 id-token: write
@@ -55,31 +53,27 @@
55 - name: Deploy to ECS
56 env:
57 ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
58 IMAGE_TAG: ${{ github.sha }}
59 run: |
60 # Get current task definition
61 TASK_DEF=$(aws ecs describe-task-definition \
62 --task-definition $TASK_FAMILY \
63 --query 'taskDefinition' \
64 --output json)
65
66 # Update image in container definitions, strip read-only fields
67 NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
68 --arg IMAGE "$ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG" \
69 '.containerDefinitions[0].image = $IMAGE |
70 del(.taskDefinitionArn, .revision, .status,
71 .requiresAttributes, .compatibilities,
72 .registeredAt, .registeredBy, .deregisteredAt)')
73
74 # Register new task definition
75 NEW_TASK_ARN=$(aws ecs register-task-definition \
76 --cli-input-json "$NEW_TASK_DEF" \
77 --query 'taskDefinition.taskDefinitionArn' \
78 --output text)
79
80 # Update service with new task definition
81 aws ecs update-service \
82 --cluster $ECS_CLUSTER \
83 --service $ECS_SERVICE \
84 --task-definition "$NEW_TASK_ARN" \
85 --force-new-deployment
86
87 DDED .github/workflows/promote.yaml
--- .github/workflows/deploy.yaml
+++ .github/workflows/deploy.yaml
@@ -8,21 +8,19 @@
8 - 'mkdocs.yml'
9 - '*.md'
10
11 env:
12 AWS_REGION: us-west-2
13 ECR_REPO: fossilrepo
14 ECS_CLUSTER: dev-fossilrepo
15 ECS_SERVICE: dev-fossilrepo-app
16 TASK_FAMILY: dev-fossilrepo-app
17
18 jobs:
 
19 ci:
20 uses: ./.github/workflows/ci.yaml
21
 
22 deploy:
23 needs: [ci]
24 runs-on: ubuntu-latest
25 permissions:
26 id-token: write
@@ -55,31 +53,27 @@
53 - name: Deploy to ECS
54 env:
55 ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
56 IMAGE_TAG: ${{ github.sha }}
57 run: |
 
58 TASK_DEF=$(aws ecs describe-task-definition \
59 --task-definition $TASK_FAMILY \
60 --query 'taskDefinition' \
61 --output json)
62
 
63 NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
64 --arg IMAGE "$ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG" \
65 '.containerDefinitions[0].image = $IMAGE |
66 del(.taskDefinitionArn, .revision, .status,
67 .requiresAttributes, .compatibilities,
68 .registeredAt, .registeredBy, .deregisteredAt)')
69
 
70 NEW_TASK_ARN=$(aws ecs register-task-definition \
71 --cli-input-json "$NEW_TASK_DEF" \
72 --query 'taskDefinition.taskDefinitionArn' \
73 --output text)
74
 
75 aws ecs update-service \
76 --cluster $ECS_CLUSTER \
77 --service $ECS_SERVICE \
78 --task-definition "$NEW_TASK_ARN" \
79 --force-new-deployment
80
81 DDED .github/workflows/promote.yaml
--- a/.github/workflows/promote.yaml
+++ b/.github/workflows/promote.yaml
@@ -0,0 +1,94 @@
1
+name: Promote to Production
2
+
3
+on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+env:
9
+ AWS_REGION: us-west-2
10
+ ECR_REPO: fossilrepo
11
+ ECS_CLUSTER: prd-fossilhub
12
+ ECS_SERVICE: prd-fossilhub-app
13
+ TASK_FAMILY: prd-fossilhub-app
14
+
15
+jobs:
16
+ promote:
17
+ runs-on: ubuntu-latest
18
+ permissions:
19
+ id-token: write
20
+ contents: read
21
+
22
+ steps:
23
+ - uses: aws-actions/configure-aws-credentials@v4
24
+ with:
25
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
26
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
27
+ aws-region: ${{ env.AWS_REGION }}
28
+
29
+ - uses: aws-actions/amazon-ecr-login@v2
30
+ id: ecr
31
+
32
+ - name: Tag image as stable + version
33
+ env:
34
+ ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
35
+ VERSION_TAG: ${{ github.ref_name }}
36
+ run: |
37
+ # Pull the latest image (what dev is running)
38
+ MANIFEST=$(aws ecr batch-get-image \
39
+ --repository-name $ECR_REPO \
40
+ --image-ids imageTag=latest \
41
+ --query 'images[0].imageManifest' \
42
+ --output text)
43
+
44
+ # Tag it with the version
45
+ aws ecr put-image \
46
+ --repository-name $ECR_REPO \
47
+ --image-tag "$VERSION_TAG" \
48
+ --image-manifest "$MANIFEST" || true
49
+
50
+ # Tag it as stable
51
+ aws ecr put-image \
52
+ --repository-name $ECR_REPO \
53
+ --image-tag stable \
54
+ --image-manifest "$MANIFEST" || true
55
+
56
+ echo "Promoted latest → $VERSION_TAG + stable"
57
+
58
+ - name: Deploy to production ECS
59
+ env:
60
+ ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
61
+ VERSION_TAG: ${{ github.ref_name }}
62
+ run: |
63
+ TASK_DEF=$(aws ecs describe-task-definition \
64
+ --task-definition $TASK_FAMILY \
65
+ --query 'taskDefinition' \
66
+ --output json)
67
+
68
+ NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
69
+ --arg IMAGE "$ECR_REGISTRY/$ECR_REPO:$VERSION_TAG" \
70
+ '.containerDefinitions[0].image = $IMAGE |
71
+ del(.taskDefinitionArn, .revision, .status,
72
+ .requiresAttributes, .compatibilities,
73
+ .registeredAt, .registeredBy, .deregisteredAt)')
74
+
75
+ NEW_TASK_ARN=$(aws ecs register-task-definition \
76
+ --cli-input-json "$NEW_TASK_DEF" \
77
+ --query 'taskDefinition.taskDefinitionArn' \
78
+ --output text)
79
+
80
+ aws ecs update-service \
81
+ --cluster $ECS_CLUSTER \
82
+ --service $ECS_SERVICE \
83
+ --task-definition "$NEW_TASK_ARN" \
84
+ --force-new-deployment
85
+
86
+ echo "Deployed $VERSION_TAG to production"
87
+
88
+ - name: Wait for deployment to stabilize
89
+ run: |
90
+ echo "Waiting for production to reach steady state..."
91
+ aws ecs wait services-stable \
92
+ --cluster $ECS_CLUSTER \
93
+ --services $ECS_SERVICE
94
+ echo "Production deployment stable."
--- a/.github/workflows/promote.yaml
+++ b/.github/workflows/promote.yaml
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/.github/workflows/promote.yaml
+++ b/.github/workflows/promote.yaml
@@ -0,0 +1,94 @@
1 name: Promote to Production
2
3 on:
4 push:
5 tags:
6 - 'v*'
7
8 env:
9 AWS_REGION: us-west-2
10 ECR_REPO: fossilrepo
11 ECS_CLUSTER: prd-fossilhub
12 ECS_SERVICE: prd-fossilhub-app
13 TASK_FAMILY: prd-fossilhub-app
14
15 jobs:
16 promote:
17 runs-on: ubuntu-latest
18 permissions:
19 id-token: write
20 contents: read
21
22 steps:
23 - uses: aws-actions/configure-aws-credentials@v4
24 with:
25 aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
26 aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
27 aws-region: ${{ env.AWS_REGION }}
28
29 - uses: aws-actions/amazon-ecr-login@v2
30 id: ecr
31
32 - name: Tag image as stable + version
33 env:
34 ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
35 VERSION_TAG: ${{ github.ref_name }}
36 run: |
37 # Pull the latest image (what dev is running)
38 MANIFEST=$(aws ecr batch-get-image \
39 --repository-name $ECR_REPO \
40 --image-ids imageTag=latest \
41 --query 'images[0].imageManifest' \
42 --output text)
43
44 # Tag it with the version
45 aws ecr put-image \
46 --repository-name $ECR_REPO \
47 --image-tag "$VERSION_TAG" \
48 --image-manifest "$MANIFEST" || true
49
50 # Tag it as stable
51 aws ecr put-image \
52 --repository-name $ECR_REPO \
53 --image-tag stable \
54 --image-manifest "$MANIFEST" || true
55
56 echo "Promoted latest → $VERSION_TAG + stable"
57
58 - name: Deploy to production ECS
59 env:
60 ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
61 VERSION_TAG: ${{ github.ref_name }}
62 run: |
63 TASK_DEF=$(aws ecs describe-task-definition \
64 --task-definition $TASK_FAMILY \
65 --query 'taskDefinition' \
66 --output json)
67
68 NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
69 --arg IMAGE "$ECR_REGISTRY/$ECR_REPO:$VERSION_TAG" \
70 '.containerDefinitions[0].image = $IMAGE |
71 del(.taskDefinitionArn, .revision, .status,
72 .requiresAttributes, .compatibilities,
73 .registeredAt, .registeredBy, .deregisteredAt)')
74
75 NEW_TASK_ARN=$(aws ecs register-task-definition \
76 --cli-input-json "$NEW_TASK_DEF" \
77 --query 'taskDefinition.taskDefinitionArn' \
78 --output text)
79
80 aws ecs update-service \
81 --cluster $ECS_CLUSTER \
82 --service $ECS_SERVICE \
83 --task-definition "$NEW_TASK_ARN" \
84 --force-new-deployment
85
86 echo "Deployed $VERSION_TAG to production"
87
88 - name: Wait for deployment to stabilize
89 run: |
90 echo "Waiting for production to reach steady state..."
91 aws ecs wait services-stable \
92 --cluster $ECS_CLUSTER \
93 --services $ECS_SERVICE
94 echo "Production deployment stable."

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button