Skip to content

Commit 43bb3fc

Browse files
authored
Merge pull request #5 from segmentio/wdbetts/terracode-pr-automation
Add automated deployment pipeline with DRY design
2 parents 4e4b22f + 0915292 commit 43bb3fc

File tree

3 files changed

+200
-16
lines changed

3 files changed

+200
-16
lines changed

.buildkite/pipeline.yml

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,6 @@ steps:
5050
- vendor/
5151
- data/
5252

53-
- label: ":golang: Go vet"
54-
key: vet
55-
depends_on: vendor
56-
commands:
57-
- make vet
58-
plugins:
59-
- ssh://[email protected]/segmentio/cache-buildkite-plugin#v3.0.1:
60-
key: "kubeapply-deps-{{ checksum \"go.sum\" }}"
61-
paths:
62-
- vendor/
63-
- data/
6453

6554
# Step 3: Testing with coverage
6655
- label: ":golang::test_tube::coverage: Unit Tests and Coverage"
@@ -92,10 +81,9 @@ steps:
9281
key: build-cli
9382
depends_on:
9483
- lint
95-
- vet
84+
- test
9685
commands:
9786
- make kubeapply
98-
# Artifact not used
9987
plugins:
10088
- ssh://[email protected]/segmentio/cache-buildkite-plugin#v3.0.1:
10189
key: "kubeapply-deps-{{ checksum \"go.sum\" }}"
@@ -107,7 +95,7 @@ steps:
10795
key: build-server
10896
depends_on:
10997
- lint
110-
- vet
98+
- test
11199
commands:
112100
- make kubeapply-server
113101
plugins:
@@ -121,7 +109,7 @@ steps:
121109
key: build-lambda
122110
depends_on:
123111
- lint
124-
- vet
112+
- test
125113
commands:
126114
- make kubeapply-lambda
127115
- make kubeapply-lambda-kubeapply
@@ -194,4 +182,55 @@ steps:
194182
imager buildpush . -f Dockerfile.lambda -d all-${ENV} \
195183
--build-arg VERSION_REF=$(git describe --tags --always --dirty="-dev") \
196184
--destination-aliases regions.yaml \
197-
--repository kubeapply-lambda
185+
--repository kubeapply-lambda
186+
187+
# Step 8: Prepare stage deployment
188+
- label: ":package: Prepare Stage Deployment"
189+
key: prepare-stage
190+
depends_on: docker-push
191+
# Only run stage deployment on main branch
192+
if: build.branch == pipeline.default_branch
193+
commands:
194+
- echo "Preparing stage deployment branch..."
195+
- chmod +x scripts/deploy-to-env.sh
196+
- ./scripts/deploy-to-env.sh stage false
197+
198+
# Manual step to create stage PR
199+
- block: ":point_right: Create Stage PR"
200+
key: create-stage-pr
201+
# Only run stage deployment on main branch
202+
if: build.branch == pipeline.default_branch
203+
depends_on: prepare-stage
204+
prompt: "Stage deployment branch is ready. Create PR?"
205+
blocked_state: passed
206+
207+
# Step 9: Create stage deployment PR
208+
- label: ":rocket: Create Stage PR"
209+
key: deploy-stage
210+
depends_on: create-stage-pr
211+
# Only run stage deployment on main branch
212+
if: build.branch == pipeline.default_branch
213+
commands:
214+
- echo "Creating stage deployment PR..."
215+
- chmod +x scripts/deploy-to-env.sh
216+
- ./scripts/deploy-to-env.sh stage true
217+
218+
# Manual gate before production deployment
219+
- block: ":warning: Deploy to Production?"
220+
key: production-gate
221+
depends_on: deploy-stage
222+
# Only run on version tags for production
223+
if: build.env("BUILDKITE_TAG") =~ /^v[0-9]+\.[0-9]+\.[0-9]+/
224+
prompt: "Stage deployment completed. Deploy to production?"
225+
blocked_state: passed
226+
227+
# Step 10: Create production deployment PR
228+
- label: ":rocket: Deploy to Production"
229+
key: deploy-production
230+
depends_on: production-gate
231+
# Only run on version tags for production
232+
if: build.env("BUILDKITE_TAG") =~ /^v[0-9]+\.[0-9]+\.[0-9]+/
233+
commands:
234+
- echo "Creating production deployment PR..."
235+
- chmod +x scripts/deploy-to-env.sh
236+
- ./scripts/deploy-to-env.sh production true

scripts/breakglass_buildpush.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
if [ -z "$1" ]; then
6+
echo "Usage: ./buildpush.sh stage|prod"
7+
exit
8+
fi
9+
10+
if [ $1 != "stage" -a $1 != "prod" ]; then
11+
echo "Usage: ./buildpush.sh stage|prod"
12+
exit
13+
fi
14+
15+
ENV=$1
16+
UPLOADER_ROLE="arn:aws:iam::752180062774:role/kubeapply-uploader"
17+
if [ $1 != "prod" ]; then
18+
UPLOADER_ROLE="arn:aws:iam::355207333203:role/kubeapply-uploader"
19+
fi
20+
21+
KUBEAPPLY_LAMBDA_SCRIPT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
22+
23+
cd $GOPATH/src/github.com/segmentio/kubeapply
24+
25+
aws-okta exec $ENV-write -- cloud-toolbox assume-roles $UPLOADER_ROLE -- imager buildpush . -f Dockerfile.lambda -d all-${ENV} \
26+
--build-arg VERSION_REF=`git describe --tags --always --dirty="-dev"` \
27+
--destination-aliases $KUBEAPPLY_LAMBDA_SCRIPT_ROOT/regions.yaml \
28+
--repository kubeapply-lambda --local

scripts/deploy-to-env.sh

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Deploy kubeapply to specified environment via terraform PR
5+
# Usage: deploy-to-env.sh <environment> [create-pr]
6+
# environment: "stage" or "production"
7+
# create-pr: if "true", creates PR automatically; if "false", just prepares branch
8+
9+
ENVIRONMENT=${1:-}
10+
CREATE_PR=${2:-true}
11+
12+
if [[ -z "$ENVIRONMENT" ]]; then
13+
echo "❌ Error: Environment required (stage or production)"
14+
exit 1
15+
fi
16+
17+
if [[ "$ENVIRONMENT" != "stage" && "$ENVIRONMENT" != "production" ]]; then
18+
echo "❌ Error: Environment must be 'stage' or 'production'"
19+
exit 1
20+
fi
21+
22+
# Get the image tag from git
23+
IMAGE_TAG=$(git describe --tags --always --dirty="-dev")
24+
echo "🏷️ Deploying image tag: $IMAGE_TAG to $ENVIRONMENT"
25+
26+
# Clone terracode-infra repository
27+
WORK_DIR="/tmp/terracode-infra-$ENVIRONMENT-$$"
28+
git clone https://github.com/segmentio/terracode-infra.git "$WORK_DIR"
29+
cd "$WORK_DIR"
30+
31+
# Configure git user for commits
32+
git config user.email "[email protected]"
33+
git config user.name "buildkite-kubeapply-pipeline"
34+
35+
# Create a new branch for the deployment
36+
BRANCH_NAME="kubeapply-$ENVIRONMENT-deploy-$IMAGE_TAG-$(date +%s)"
37+
git checkout -b "$BRANCH_NAME"
38+
39+
# Update terraform configs based on environment
40+
if [[ "$ENVIRONMENT" == "stage" ]]; then
41+
echo "📝 Updating stage terraform configs..."
42+
sed -i "s/lambda_image_tag.*=.*\".*\"/lambda_image_tag = \"$IMAGE_TAG\"/" stage/eu-west-1/common-kubeapply/config.tf
43+
sed -i "s/lambda_image_tag.*=.*\".*\"/lambda_image_tag = \"$IMAGE_TAG\"/" stage/us-west-2/core/kubeapply/config.tf
44+
git add stage/*/*/kubeapply/config.tf stage/*/common-kubeapply/config.tf
45+
REGIONS="eu-west-1, us-west-2"
46+
elif [[ "$ENVIRONMENT" == "production" ]]; then
47+
echo "📝 Updating production terraform config..."
48+
sed -i "s/lambda_image_tag.*=.*\".*\"/lambda_image_tag = \"$IMAGE_TAG\"/" production/us-west-2/core/kubeapply/config.tf
49+
git add production/*/*/kubeapply/config.tf
50+
REGIONS="us-west-2"
51+
fi
52+
53+
# Commit and push changes
54+
if git diff --cached --quiet; then
55+
echo "📝 No changes to commit - terraform configs already up to date with $IMAGE_TAG"
56+
else
57+
git commit -m "Deploy kubeapply $IMAGE_TAG to $ENVIRONMENT"
58+
fi
59+
git push origin "$BRANCH_NAME"
60+
61+
echo "✅ Branch created and pushed: $BRANCH_NAME"
62+
63+
# Create PR if requested
64+
if [[ "$CREATE_PR" == "true" ]]; then
65+
echo "🔄 Creating pull request..."
66+
67+
if [[ "$ENVIRONMENT" == "stage" ]]; then
68+
PR_BODY="Automated deployment of kubeapply image tag \`$IMAGE_TAG\` to stage environment.
69+
70+
**Instructions:**
71+
1. Review the changes in this PR
72+
2. Comment \`atlantis apply\` to deploy to stage environment
73+
3. Merge this PR after successful deployment
74+
75+
**Image tag:** \`$IMAGE_TAG\`
76+
**Environment:** Stage
77+
**Regions:** $REGIONS"
78+
else
79+
PR_BODY="Automated deployment of kubeapply image tag \`$IMAGE_TAG\` to production environment.
80+
81+
**Instructions:**
82+
1. Review the changes in this PR carefully
83+
2. Comment \`atlantis apply\` to deploy to production environment
84+
3. Merge this PR after successful deployment
85+
86+
**Image tag:** \`$IMAGE_TAG\`
87+
**Environment:** Production
88+
**Region:** $REGIONS"
89+
fi
90+
91+
PR_URL=$(gh pr create \
92+
--title "Deploy kubeapply $IMAGE_TAG to $ENVIRONMENT" \
93+
--body "$PR_BODY" \
94+
--head "$BRANCH_NAME" \
95+
--base master)
96+
97+
echo "✅ Pull request created!"
98+
echo "🔗 PR URL: $PR_URL"
99+
echo "📋 Instructions: Go to the PR and comment 'atlantis apply' to deploy to $ENVIRONMENT."
100+
101+
# Add Buildkite annotation with deployment information
102+
buildkite-agent annotate --style info "🚀 **Deployment PR Created**
103+
104+
📦 **Image tag:** \`$IMAGE_TAG\`
105+
🌍 **Environment:** $ENVIRONMENT
106+
🗺️ **Regions:** $REGIONS
107+
108+
🔗 **[View Deployment PR]($PR_URL)**
109+
110+
**Next Steps:**
111+
1. Review the changes in the deployment PR
112+
2. Comment \`atlantis apply\` on the PR to deploy to $ENVIRONMENT
113+
3. Merge the PR after successful deployment"
114+
else
115+
echo "📋 Branch ready for manual PR creation: $BRANCH_NAME"
116+
echo "🔗 Create PR at: https://github.com/segmentio/terracode-infra/compare/master...$BRANCH_NAME"
117+
fi

0 commit comments

Comments
 (0)