Skip to content

Commit 4de4563

Browse files
daroradragarcia
andauthored
feat: Build and publish a QEMU image artifact (#1430)
Co-authored-by: angelico <[email protected]>
1 parent ba21d04 commit 4de4563

19 files changed

+840
-207
lines changed

.github/workflows/ami-release-nix.yml

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ jobs:
7878
run: |
7979
packer init amazon-arm64-nix.pkr.hcl
8080
GIT_SHA=${{github.sha}}
81+
# why is postgresql_major defined here instead of where the _three_ other postgresql_* variables are defined?
8182
packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "ansible_arguments=-e postgresql_major=${POSTGRES_MAJOR_VERSION}" amazon-arm64-nix.pkr.hcl
8283
8384
- name: Build AMI stage 2
+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
name: Build QEMU image
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
- release/*
8+
paths:
9+
- '.github/workflows/qemu-image-build.yml'
10+
- 'qemu-arm64-nix.pkr.hcl'
11+
- 'common-nix.vars.pkr.hcl'
12+
- 'ansible/vars.yml'
13+
workflow_dispatch:
14+
15+
jobs:
16+
prepare:
17+
runs-on: ubuntu-latest
18+
outputs:
19+
postgres_versions: ${{ steps.set-versions.outputs.postgres_versions }}
20+
steps:
21+
- name: Checkout Repo
22+
uses: actions/checkout@v3
23+
24+
- uses: DeterminateSystems/nix-installer-action@main
25+
26+
- name: Set PostgreSQL versions - only builds pg15 atm
27+
id: set-versions
28+
run: |
29+
VERSIONS=$(nix run nixpkgs#yq -- '.postgres_major[0]' ansible/vars.yml | nix run nixpkgs#jq -- -R -s -c 'split("\n")[:-1]')
30+
echo "postgres_versions=$VERSIONS" >> $GITHUB_OUTPUT
31+
32+
build:
33+
needs: prepare
34+
strategy:
35+
matrix:
36+
postgres_version: ${{ fromJson(needs.prepare.outputs.postgres_versions) }}
37+
runs-on: arm-native-runner
38+
timeout-minutes: 150
39+
permissions:
40+
contents: write
41+
packages: write
42+
id-token: write
43+
44+
steps:
45+
- name: Checkout Repo
46+
uses: actions/checkout@v3
47+
48+
- uses: DeterminateSystems/nix-installer-action@main
49+
50+
- name: Run checks if triggered manually
51+
if: ${{ github.event_name == 'workflow_dispatch' }}
52+
run: |
53+
SUFFIX=$(sudo nix run nixpkgs#yq -- ".postgres_release[\"postgres${{ matrix.postgres_version }}\"]" ansible/vars.yml | sed -E 's/[0-9\.]+(.*)$/\1/')
54+
if [[ -z $SUFFIX ]] ; then
55+
echo "Version must include non-numeric characters if built manually."
56+
exit 1
57+
fi
58+
59+
- name: enable KVM support
60+
run: |
61+
sudo chown runner /dev/kvm
62+
sudo chmod 666 /dev/kvm
63+
64+
- name: Set PostgreSQL version environment variable
65+
run: echo "POSTGRES_MAJOR_VERSION=${{ matrix.postgres_version }}" >> $GITHUB_ENV
66+
67+
- name: Generate common-nix.vars.pkr.hcl
68+
run: |
69+
curl -L https://github.com/mikefarah/yq/releases/download/v4.45.1/yq_linux_arm64 -o yq && chmod +x yq
70+
PG_VERSION=$(./yq '.postgres_release["postgres'${{ matrix.postgres_version }}'"]' ansible/vars.yml)
71+
PG_VERSION=$(echo $PG_VERSION | tr -d '"') # Remove any surrounding quotes
72+
echo 'postgres-version = "'$PG_VERSION'"' > common-nix.vars.pkr.hcl
73+
echo 'postgres-major-version = "'$POSTGRES_MAJOR_VERSION'"' >> common-nix.vars.pkr.hcl
74+
# Ensure there's a newline at the end of the file
75+
echo "" >> common-nix.vars.pkr.hcl
76+
77+
# TODO (darora): not quite sure why I'm having to uninstall and re-install these deps, but the build fails w/o this
78+
- name: Install dependencies
79+
run: |
80+
sudo apt-get update
81+
sudo apt-get remove -y qemu-efi-aarch64 cloud-image-utils qemu-system-arm qemu-utils
82+
sudo apt-get install -y qemu-efi-aarch64 cloud-image-utils qemu-system-arm qemu-utils
83+
84+
- name: Build QEMU artifact
85+
run: |
86+
make init
87+
GIT_SHA=${{github.sha}}
88+
export PACKER_LOG=1
89+
packer build -var "git_sha=${GIT_SHA}" -var-file="common-nix.vars.pkr.hcl" qemu-arm64-nix.pkr.hcl
90+
91+
- name: Grab release version
92+
id: process_release_version
93+
run: |
94+
VERSION=$(cat common-nix.vars.pkr.hcl | sed -e 's/postgres-version = "\(.*\)"/\1/g')
95+
echo "version=$VERSION" >> $GITHUB_OUTPUT
96+
97+
# - name: Create nix flake revision tarball
98+
# run: |
99+
# GIT_SHA=${{github.sha}}
100+
# MAJOR_VERSION=${{ env.POSTGRES_MAJOR_VERSION }}
101+
102+
# mkdir -p "/tmp/pg_upgrade_bin/${MAJOR_VERSION}"
103+
# echo "$GIT_SHA" >> "/tmp/pg_upgrade_bin/${MAJOR_VERSION}/nix_flake_version"
104+
# tar -czf "/tmp/pg_binaries.tar.gz" -C "/tmp/pg_upgrade_bin" .
105+
106+
- name: configure aws credentials - staging
107+
uses: aws-actions/configure-aws-credentials@v4
108+
with:
109+
role-to-assume: ${{ secrets.DEV_AWS_ROLE }}
110+
aws-region: "us-east-1"
111+
112+
- name: Login to Amazon ECR Public
113+
id: login-ecr-public
114+
uses: aws-actions/amazon-ecr-login@v2
115+
with:
116+
registry-type: public
117+
118+
- name: Build, tag, and push docker image to Amazon ECR Public
119+
env:
120+
REGISTRY: public.ecr.aws/w9p6e7k7
121+
REGISTRY_ALIAS: supabase
122+
REPOSITORY: postgres-vm-image
123+
IMAGE_TAG: ${{ steps.process_release_version.outputs.version }}
124+
run: |
125+
docker build -f Dockerfile-kubernetes -t $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG .
126+
docker push $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG
127+
128+
# - name: Upload software manifest to s3 staging
129+
# run: |
130+
# cd ansible
131+
# ansible-playbook -i localhost \
132+
# -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \
133+
# -e "internal_artifacts_bucket=${{ secrets.ARTIFACTS_BUCKET }}" \
134+
# -e "postgres_major_version=${{ env.POSTGRES_MAJOR_VERSION }}" \
135+
# manifest-playbook.yml
136+
137+
# - name: Upload nix flake revision to s3 staging
138+
# run: |
139+
# aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz
140+
141+
# - name: configure aws credentials - prod
142+
# uses: aws-actions/configure-aws-credentials@v4
143+
# with:
144+
# role-to-assume: ${{ secrets.PROD_AWS_ROLE }}
145+
# aws-region: "us-east-1"
146+
147+
# - name: Upload software manifest to s3 prod
148+
# run: |
149+
# cd ansible
150+
# ansible-playbook -i localhost \
151+
# -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \
152+
# -e "internal_artifacts_bucket=${{ secrets.PROD_ARTIFACTS_BUCKET }}" \
153+
# -e "postgres_major_version=${{ env.POSTGRES_MAJOR_VERSION }}" \
154+
# manifest-playbook.yml
155+
156+
# - name: Upload nix flake revision to s3 prod
157+
# run: |
158+
# aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz
159+
160+
# - name: Create release
161+
# uses: softprops/action-gh-release@v1
162+
# with:
163+
# name: ${{ steps.process_release_version.outputs.version }}
164+
# tag_name: ${{ steps.process_release_version.outputs.version }}
165+
# target_commitish: ${{github.sha}}
166+
167+
# - name: Slack Notification on Failure
168+
# if: ${{ failure() }}
169+
# uses: rtCamp/action-slack-notify@v2
170+
# env:
171+
# SLACK_WEBHOOK: ${{ secrets.SLACK_NOTIFICATIONS_WEBHOOK }}
172+
# SLACK_USERNAME: 'gha-failures-notifier'
173+
# SLACK_COLOR: 'danger'
174+
# SLACK_MESSAGE: 'Building Postgres AMI failed'
175+
# SLACK_FOOTER: ''
176+
177+
- name: Cleanup resources after build
178+
if: ${{ always() }}
179+
run: |
180+
aws ec2 describe-instances --filters "Name=tag:packerExecutionId,Values=${GITHUB_RUN_ID}" --query "Reservations[].Instances[].InstanceId" --output text | xargs -r aws ec2 terminate-instances --instance-ids
181+
182+
- name: Cleanup resources on build cancellation
183+
if: ${{ cancelled() }}
184+
run: |
185+
aws ec2 describe-instances --filters "Name=tag:packerExecutionId,Values=${GITHUB_RUN_ID}" --query "Reservations[].Instances[].InstanceId" --output text | xargs -r aws ec2 terminate-instances --instance-ids

Dockerfile-kubernetes

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM alpine:3.21
2+
3+
ADD ./output-cloudimg/packer-cloudimg /disk/focal.qcow2
4+
5+
RUN apk add --no-cache qemu-system-aarch64 qemu-img openssh-client nftables cloud-utils-localds aavmf
6+
# dev stuff
7+
# RUN apk add --no-cache iproute2
8+
9+
CMD exec /bin/sh -c "trap : TERM INT; sleep 9999999999d & wait"

Makefile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
UPSTREAM_NIX_GIT_SHA := $(shell git rev-parse HEAD)
2+
GIT_SHA := $(shell git describe --tags --always --dirty)
3+
4+
init: qemu-arm64-nix.pkr.hcl
5+
packer init qemu-arm64-nix.pkr.hcl
6+
7+
output-cloudimg/packer-cloudimg: ansible qemu-arm64-nix.pkr.hcl
8+
packer build -var "git_sha=$(UPSTREAM_NIX_GIT_SHA)" qemu-arm64-nix.pkr.hcl
9+
10+
disk/focal-raw.img: output-cloudimg/packer-cloudimg
11+
mkdir -p disk
12+
sudo qemu-img convert -O raw output-cloudimg/packer-cloudimg disk/focal-raw.img
13+
14+
alpine-image: output-cloudimg/packer-cloudimg
15+
sudo nerdctl build . -t supabase-postgres-test:$(GIT_SHA) -f ./Dockerfile-kubernetes
16+
17+
clean:
18+
rm -rf output-cloudimg
19+
20+
.PHONY: alpine-image init clean

amazon-arm64-nix.pkr.hcl

+1-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ build {
264264
]
265265
use_env_var_file = true
266266
script = "ebssurrogate/scripts/surrogate-bootstrap-nix.sh"
267-
execute_command = "sudo -S sh -c '. {{.EnvVarFile}} && {{.Path}}'"
267+
execute_command = "sudo -S sh -c '. {{.EnvVarFile}} && cd /tmp/ansible-playbook && {{.Path}}'"
268268
start_retry_timeout = "5m"
269269
skip_clean = true
270270
}

0 commit comments

Comments
 (0)