Skip to content

Commit 13cb2a0

Browse files
committed
u
Signed-off-by: Joe Isaacs <[email protected]>
1 parent db44ca6 commit 13cb2a0

File tree

3 files changed

+320
-2
lines changed

3 files changed

+320
-2
lines changed
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
name: "Build Vortex CI AMI"
2+
description: "Build a custom Amazon Machine Image for Vortex CI runners"
3+
4+
inputs:
5+
arch:
6+
description: "Target architecture: x64 or arm64"
7+
required: true
8+
aws-region:
9+
description: "AWS region to build AMI in"
10+
required: false
11+
default: "us-east-1"
12+
ami-prefix:
13+
description: "Prefix for AMI name"
14+
required: false
15+
default: "vortex-ci"
16+
retention-days:
17+
description: "Number of days before AMI is deprecated"
18+
required: false
19+
default: "30"
20+
rust-toolchain:
21+
description: "Rust toolchain version (reads from rust-toolchain.toml if empty)"
22+
required: false
23+
default: ""
24+
protoc-version:
25+
description: "Protocol Buffers compiler version"
26+
required: false
27+
default: "29.3"
28+
flatc-version:
29+
description: "FlatBuffers compiler version"
30+
required: false
31+
default: "25.9.23"
32+
33+
outputs:
34+
ami-id:
35+
description: "The ID of the built AMI"
36+
value: ${{ steps.create-ami.outputs.ami_id }}
37+
ami-name:
38+
description: "The name of the built AMI"
39+
value: ${{ steps.create-ami.outputs.ami_name }}
40+
41+
runs:
42+
using: "composite"
43+
steps:
44+
- name: Resolve Rust Toolchain
45+
id: toolchain
46+
shell: bash
47+
run: |
48+
if [ -n "${{ inputs.rust-toolchain }}" ]; then
49+
echo "version=${{ inputs.rust-toolchain }}" >> $GITHUB_OUTPUT
50+
elif [ -f rust-toolchain.toml ]; then
51+
VERSION=$(grep channel rust-toolchain.toml | awk -F'"' '{print $2}')
52+
echo "version=$VERSION" >> $GITHUB_OUTPUT
53+
else
54+
echo "version=stable" >> $GITHUB_OUTPUT
55+
fi
56+
57+
- name: Install dependencies
58+
shell: bash
59+
run: |
60+
sudo apt-get update
61+
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
62+
build-essential \
63+
curl \
64+
git \
65+
ca-certificates \
66+
pkg-config \
67+
libssl-dev \
68+
cmake \
69+
ninja-build \
70+
clang \
71+
lld \
72+
llvm \
73+
jq \
74+
unzip \
75+
zip \
76+
zstd \
77+
python3 \
78+
python3-pip \
79+
python3-venv \
80+
libicu74 \
81+
libkrb5-3 \
82+
zlib1g \
83+
libcurl4-openssl-dev
84+
85+
- name: Install mold linker
86+
shell: bash
87+
run: |
88+
MOLD_VERSION=$(curl -s https://api.github.com/repos/rui314/mold/releases/latest | jq -r .tag_name | sed 's/v//')
89+
ARCH=$(uname -m)
90+
curl -fsSL "https://github.com/rui314/mold/releases/download/v${MOLD_VERSION}/mold-${MOLD_VERSION}-${ARCH}-linux.tar.gz" \
91+
| sudo tar -xz -C /usr/local --strip-components=1
92+
mold --version
93+
94+
- name: Install Rust
95+
shell: bash
96+
env:
97+
RUST_TOOLCHAIN: ${{ steps.toolchain.outputs.version }}
98+
run: |
99+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "$RUST_TOOLCHAIN"
100+
source "$HOME/.cargo/env"
101+
rustup component add clippy rustfmt
102+
rustup toolchain install nightly --component rustfmt clippy rust-src miri llvm-tools-preview
103+
cargo --version
104+
rustc --version
105+
106+
- name: Install protoc
107+
shell: bash
108+
env:
109+
PROTOC_VERSION: ${{ inputs.protoc-version }}
110+
run: |
111+
ARCH=$(uname -m)
112+
if [ "$ARCH" = "x86_64" ]; then PROTOC_ARCH=linux-x86_64; else PROTOC_ARCH=linux-aarch_64; fi
113+
curl -fsSL -o /tmp/protoc.zip "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${PROTOC_ARCH}.zip"
114+
sudo unzip -o /tmp/protoc.zip -d /usr/local bin/protoc 'include/*'
115+
sudo chmod +x /usr/local/bin/protoc
116+
rm /tmp/protoc.zip
117+
protoc --version
118+
119+
- name: Install flatc
120+
shell: bash
121+
env:
122+
FLATC_VERSION: ${{ inputs.flatc-version }}
123+
run: |
124+
ARCH=$(uname -m)
125+
if [ "$ARCH" = "x86_64" ]; then
126+
curl -fsSL -o /tmp/flatc.zip "https://github.com/nicholasguan/flatbuffers/releases/download/v${FLATC_VERSION}/Linux.flatc.binary.clang++-18.zip"
127+
sudo unzip -o /tmp/flatc.zip -d /usr/local/bin
128+
sudo chmod +x /usr/local/bin/flatc
129+
rm /tmp/flatc.zip
130+
else
131+
git clone --depth 1 --branch "v${FLATC_VERSION}" https://github.com/google/flatbuffers.git /tmp/flatbuffers
132+
cd /tmp/flatbuffers && cmake -G Ninja -DCMAKE_BUILD_TYPE=Release && ninja
133+
sudo cp flatc /usr/local/bin/
134+
rm -rf /tmp/flatbuffers
135+
fi
136+
flatc --version
137+
138+
- name: Install sccache
139+
shell: bash
140+
run: |
141+
SCCACHE_VERSION=$(curl -s https://api.github.com/repos/mozilla/sccache/releases/latest | jq -r .tag_name | sed 's/v//')
142+
ARCH=$(uname -m)
143+
if [ "$ARCH" = "x86_64" ]; then SCCACHE_ARCH=x86_64-unknown-linux-musl; else SCCACHE_ARCH=aarch64-unknown-linux-musl; fi
144+
curl -fsSL "https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-${SCCACHE_ARCH}.tar.gz" \
145+
| sudo tar -xz -C /usr/local/bin --strip-components=1 "sccache-v${SCCACHE_VERSION}-${SCCACHE_ARCH}/sccache"
146+
sudo chmod +x /usr/local/bin/sccache
147+
sccache --version
148+
149+
- name: Install cargo tools
150+
shell: bash
151+
run: |
152+
source "$HOME/.cargo/env"
153+
cargo install cargo-nextest --locked
154+
cargo install cargo-hack --locked
155+
cargo install grcov --locked
156+
157+
- name: Setup environment
158+
shell: bash
159+
run: |
160+
echo 'source $HOME/.cargo/env' >> "$HOME/.bashrc"
161+
echo 'export PATH=$HOME/.cargo/bin:/usr/local/bin:$PATH' >> "$HOME/.bashrc"
162+
163+
- name: Get instance ID
164+
id: instance
165+
shell: bash
166+
run: |
167+
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
168+
echo "instance_id=$INSTANCE_ID" >> $GITHUB_OUTPUT
169+
170+
- name: Create AMI
171+
id: create-ami
172+
shell: bash
173+
env:
174+
AWS_REGION: ${{ inputs.aws-region }}
175+
AMI_PREFIX: ${{ inputs.ami-prefix }}
176+
ARCH: ${{ inputs.arch }}
177+
RETENTION_DAYS: ${{ inputs.retention-days }}
178+
run: |
179+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
180+
AMI_NAME="${AMI_PREFIX}-${ARCH}-${TIMESTAMP}"
181+
DEPRECATION_TIME=$(date -u -d "+${RETENTION_DAYS} days" +%Y-%m-%dT%H:%M:%SZ)
182+
183+
echo "Creating AMI: $AMI_NAME"
184+
AMI_ID=$(aws ec2 create-image \
185+
--instance-id "${{ steps.instance.outputs.instance_id }}" \
186+
--name "$AMI_NAME" \
187+
--description "Vortex CI runner image for ${ARCH}" \
188+
--no-reboot \
189+
--tag-specifications "ResourceType=image,Tags=[{Key=Name,Value=$AMI_NAME},{Key=Environment,Value=ci},{Key=Arch,Value=$ARCH},{Key=ManagedBy,Value=github-actions}]" \
190+
--query 'ImageId' \
191+
--output text)
192+
193+
echo "Waiting for AMI to be available..."
194+
aws ec2 wait image-available --image-ids "$AMI_ID"
195+
196+
echo "Setting deprecation time to $DEPRECATION_TIME"
197+
aws ec2 enable-image-deprecation \
198+
--image-id "$AMI_ID" \
199+
--deprecate-at "$DEPRECATION_TIME"
200+
201+
echo "ami_id=$AMI_ID" >> $GITHUB_OUTPUT
202+
echo "ami_name=$AMI_NAME" >> $GITHUB_OUTPUT
203+
echo "AMI created: $AMI_ID ($AMI_NAME)"

.github/runs-on.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
# Custom AMIs for Vortex CI runners
2+
# These AMIs are automatically rebuilt every 15 days by the ami-prebuild.yml workflow
3+
# to keep the GitHub Actions runner agent up to date (required to be <30 days old).
4+
#
5+
# AMI naming pattern: vortex-ci-{arch}-{timestamp}
6+
# Built with: .github/actions/build-ami and .github/packer/vortex-ci.pkr.hcl
17
images:
28
vortex-ci-amd64:
39
platform: "linux"
410
arch: "x64"
5-
name: "vortex-ci-*"
11+
name: "vortex-ci-x64-*"
612
owner: "375504701696"
713
vortex-ci-arm64:
814
platform: "linux"
915
arch: "arm64"
10-
name: "vortex-ci-*"
16+
name: "vortex-ci-arm64-*"
1117
owner: "375504701696"

.github/workflows/ami-prebuild.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
name: AMI Prebuild
2+
3+
# Schedule to run every 15 days to keep runner agent up to date
4+
# GitHub stops routing jobs to runners with agents older than 30 days
5+
on:
6+
schedule:
7+
# Run at 00:00 UTC on the 1st and 16th of each month (~15 days apart)
8+
- cron: "0 0 1,16 * *"
9+
workflow_dispatch:
10+
inputs:
11+
arch:
12+
description: "Architecture to build (leave empty for both)"
13+
required: false
14+
type: choice
15+
options:
16+
- ""
17+
- x64
18+
- arm64
19+
retention-days:
20+
description: "Days until AMI deprecation"
21+
required: false
22+
type: number
23+
default: 30
24+
25+
concurrency:
26+
group: ${{ github.workflow }}
27+
cancel-in-progress: false
28+
29+
permissions:
30+
contents: read
31+
id-token: write
32+
33+
env:
34+
AWS_REGION: us-east-1
35+
36+
jobs:
37+
build-x64:
38+
name: "Build AMI (x64)"
39+
if: ${{ github.event.inputs.arch == '' || github.event.inputs.arch == 'x64' }}
40+
runs-on:
41+
- runs-on=${{ github.run_id }}
42+
- family=m7i+m7i-flex+m7a
43+
- cpu=4
44+
- image=ubuntu24-full-x64
45+
- tag=ami-prebuild-x64
46+
timeout-minutes: 60
47+
48+
steps:
49+
- name: Checkout
50+
uses: actions/checkout@v6
51+
52+
- name: Configure AWS Credentials
53+
uses: aws-actions/configure-aws-credentials@v4
54+
with:
55+
role-to-assume: arn:aws:iam::375504701696:role/GitHubAMIBuilderRole
56+
aws-region: ${{ env.AWS_REGION }}
57+
58+
- name: Build AMI
59+
id: build
60+
uses: ./.github/actions/build-ami
61+
with:
62+
arch: x64
63+
aws-region: ${{ env.AWS_REGION }}
64+
retention-days: ${{ inputs.retention-days || '30' }}
65+
66+
- name: Summary
67+
run: |
68+
echo "## AMI Build Complete (x64)" >> $GITHUB_STEP_SUMMARY
69+
echo "" >> $GITHUB_STEP_SUMMARY
70+
echo "- **AMI ID:** ${{ steps.build.outputs.ami-id }}" >> $GITHUB_STEP_SUMMARY
71+
echo "- **AMI Name:** ${{ steps.build.outputs.ami-name }}" >> $GITHUB_STEP_SUMMARY
72+
echo "- **Deprecation:** ${{ inputs.retention-days || '30' }} days" >> $GITHUB_STEP_SUMMARY
73+
74+
build-arm64:
75+
name: "Build AMI (arm64)"
76+
if: ${{ github.event.inputs.arch == '' || github.event.inputs.arch == 'arm64' }}
77+
runs-on:
78+
- runs-on=${{ github.run_id }}
79+
- family=m7g
80+
- cpu=4
81+
- image=ubuntu24-full-arm64
82+
- tag=ami-prebuild-arm64
83+
timeout-minutes: 60
84+
85+
steps:
86+
- name: Checkout
87+
uses: actions/checkout@v6
88+
89+
- name: Configure AWS Credentials
90+
uses: aws-actions/configure-aws-credentials@v4
91+
with:
92+
role-to-assume: arn:aws:iam::375504701696:role/GitHubAMIBuilderRole
93+
aws-region: ${{ env.AWS_REGION }}
94+
95+
- name: Build AMI
96+
id: build
97+
uses: ./.github/actions/build-ami
98+
with:
99+
arch: arm64
100+
aws-region: ${{ env.AWS_REGION }}
101+
retention-days: ${{ inputs.retention-days || '30' }}
102+
103+
- name: Summary
104+
run: |
105+
echo "## AMI Build Complete (arm64)" >> $GITHUB_STEP_SUMMARY
106+
echo "" >> $GITHUB_STEP_SUMMARY
107+
echo "- **AMI ID:** ${{ steps.build.outputs.ami-id }}" >> $GITHUB_STEP_SUMMARY
108+
echo "- **AMI Name:** ${{ steps.build.outputs.ami-name }}" >> $GITHUB_STEP_SUMMARY
109+
echo "- **Deprecation:** ${{ inputs.retention-days || '30' }} days" >> $GITHUB_STEP_SUMMARY

0 commit comments

Comments
 (0)