Skip to content

Commit 7fe5f99

Browse files
committed
Release workflow for cli binaries
1 parent bbb9324 commit 7fe5f99

2 files changed

Lines changed: 278 additions & 0 deletions

File tree

.github/upload.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/bin/bash
2+
# Upload an asset file to R2.
3+
4+
set -e
5+
set -o pipefail
6+
7+
CLOUDFLARE_R2_ASSETS_BUCKET_NAME=assets
8+
9+
: "${1:?"missing first argument [artifact name]"}"
10+
: "${CLOUDFLARE_ASSETS_ACCOUNT_ID:?"missing environment variable"}"
11+
: "${CLOUDFLARE_ASSETS_R2_ACCESS_KEY_ID:?"missing environment variable"}"
12+
: "${CLOUDFLARE_ASSETS_R2_SECRET_ACCESS_KEY:?"missing environment variable"}"
13+
14+
bucket_name=$CLOUDFLARE_R2_ASSETS_BUCKET_NAME
15+
endpoint_url="https://${CLOUDFLARE_ASSETS_ACCOUNT_ID}.r2.cloudflarestorage.com"
16+
17+
key="cli-extensions/$1"
18+
19+
echo "Collecting the files to be uploaded…"
20+
21+
export PATH=/usr/local/bin:$PATH
22+
23+
aws configure set default.s3.max_concurrent_requests 8
24+
aws configure set default.s3.multipart_threshold 512MB
25+
aws configure set default.s3.multipart_chunksize 128MB
26+
27+
s3_path="s3://${bucket_name}/${key}"
28+
echo "Uploading to: $s3_path"
29+
30+
# See https://developers.cloudflare.com/r2/examples/aws/aws-cli/ for the rationale behind the checksum algorithm: it is a compatibility issue between AWS CLI and R2.
31+
env -i \
32+
PATH="$PATH" \
33+
AWS_PAGER=0 \
34+
AWS_REGION=auto \
35+
AWS_ACCESS_KEY_ID="$CLOUDFLARE_ASSETS_R2_ACCESS_KEY_ID" \
36+
AWS_SECRET_ACCESS_KEY="$CLOUDFLARE_ASSETS_R2_SECRET_ACCESS_KEY" \
37+
aws --endpoint-url "$endpoint_url" s3 cp --no-progress "$1" "$s3_path" --checksum-algorithm=CRC32
38+
39+
env -i \
40+
PATH="$PATH" \
41+
AWS_PAGER=0 \
42+
AWS_REGION=auto \
43+
AWS_ACCESS_KEY_ID="$CLOUDFLARE_ASSETS_R2_ACCESS_KEY_ID" \
44+
AWS_SECRET_ACCESS_KEY="$CLOUDFLARE_ASSETS_R2_SECRET_ACCESS_KEY" \
45+
aws --endpoint-url "$endpoint_url" s3 ls "$s3_path" --human-readable
46+
47+
echo "Done."
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
name: Release CLI Extensions
2+
3+
on:
4+
push:
5+
# branches:
6+
# - main
7+
# paths:
8+
# - "cli/**/Cargo.toml"
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
RUSTFLAGS: -D warnings
13+
14+
jobs:
15+
check-versions:
16+
runs-on: ubuntu-latest
17+
outputs:
18+
matrix: ${{ steps.set-matrix.outputs.matrix }}
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
25+
- name: Install Rust
26+
uses: ./.github/actions/install-rust
27+
28+
- name: Find extensions with version changes
29+
id: set-matrix
30+
run: |
31+
echo "Checking for CLI extensions with version changes..."
32+
33+
# Initialize matrix JSON
34+
MATRIX="{\"include\":[]}"
35+
36+
# Find all CLI extension directories
37+
for EXT_DIR in cli/*/; do
38+
if [ -f "${EXT_DIR}Cargo.toml" ]; then
39+
# Extract extension name and current version
40+
EXT_NAME=$(basename $EXT_DIR)
41+
CURRENT_VERSION=$(grep -m 1 -oP 'version\s*=\s*"\K[^"]+' "${EXT_DIR}Cargo.toml")
42+
43+
echo "Found extension: $EXT_NAME, version: $CURRENT_VERSION"
44+
45+
# Check if this version already exists as a release
46+
LATEST_TAG=$(gh release list --repo ${{ github.repository }} --limit 100 | grep "^${EXT_NAME}-v" | head -n 1 | awk '{print $1}' || echo "")
47+
LATEST_VERSION=${LATEST_TAG#${EXT_NAME}-v}
48+
49+
echo "Latest released version: $LATEST_VERSION"
50+
51+
# If no release exists or current version is newer, add to matrix
52+
if [ -z "$LATEST_VERSION" ] || [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | head -n1)" != "$CURRENT_VERSION" ]; then
53+
echo "New version detected for $EXT_NAME: $CURRENT_VERSION"
54+
MATRIX=$(echo $MATRIX | jq -c '.include += [{"extension": "'$EXT_NAME'", "version": "'$CURRENT_VERSION'", "path": "'${EXT_DIR%/}'"}]')
55+
else
56+
echo "No new version for $EXT_NAME"
57+
fi
58+
fi
59+
done
60+
61+
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
62+
echo "Extensions to release: $MATRIX"
63+
env:
64+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65+
66+
build-and-release:
67+
needs: check-versions
68+
if: ${{ fromJson(needs.check-versions.outputs.matrix).include[0] }}
69+
runs-on: ubuntu-latest
70+
strategy:
71+
matrix: ${{ fromJson(needs.check-versions.outputs.matrix) }}
72+
steps:
73+
- name: Checkout code
74+
uses: actions/checkout@v4
75+
76+
- name: Install Rust
77+
uses: ./.github/actions/install-rust
78+
79+
- name: Set up cross-compilation
80+
run: |
81+
rustup target add x86_64-unknown-linux-musl
82+
rustup target add aarch64-unknown-linux-musl
83+
rustup target add x86_64-apple-darwin
84+
rustup target add aarch64-apple-darwin
85+
rustup target add x86_64-pc-windows-msvc
86+
87+
- name: Install cross-compilation tools
88+
run: |
89+
sudo apt-get update
90+
sudo apt-get install -y musl-tools gcc-aarch64-linux-gnu
91+
92+
- name: Build for Linux (x86_64-musl)
93+
run: cargo build --release --target x86_64-unknown-linux-musl
94+
working-directory: ${{ matrix.path }}
95+
96+
- name: Build for Linux (aarch64-musl)
97+
run: |
98+
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc
99+
export CC_aarch64_unknown_linux_musl=aarch64-linux-gnu-gcc
100+
cargo build --release --target aarch64-unknown-linux-musl
101+
working-directory: ${{ matrix.path }}
102+
103+
- name: Build for Windows
104+
run: cargo build --release --target x86_64-pc-windows-msvc
105+
working-directory: ${{ matrix.path }}
106+
107+
- name: Install macOS cross-compilation tools
108+
if: runner.os == 'Linux'
109+
run: |
110+
# For macOS targets on Linux, we'll use cross - a more convenient wrapper around cross-rs
111+
cargo install cross
112+
113+
- name: Build for macOS (x86_64)
114+
if: runner.os == 'Linux'
115+
run: cross build --release --target x86_64-apple-darwin
116+
working-directory: ${{ matrix.path }}
117+
118+
- name: Build for macOS (aarch64)
119+
if: runner.os == 'Linux'
120+
run: cross build --release --target aarch64-apple-darwin
121+
working-directory: ${{ matrix.path }}
122+
123+
- name: Create release artifacts directory
124+
run: mkdir -p artifacts
125+
126+
- name: Collect binaries
127+
run: |
128+
# Copy and rename binaries to match naming convention
129+
cp ${{ matrix.path }}/target/x86_64-unknown-linux-musl/release/${{ matrix.extension }} artifacts/${{ matrix.extension }}-x86_64-unknown-linux-musl
130+
cp ${{ matrix.path }}/target/aarch64-unknown-linux-musl/release/${{ matrix.extension }} artifacts/${{ matrix.extension }}-aarch64-unknown-linux-musl
131+
cp ${{ matrix.path }}/target/x86_64-pc-windows-msvc/release/${{ matrix.extension }}.exe artifacts/${{ matrix.extension }}-x86_64-pc-windows-msvc.exe
132+
cp ${{ matrix.path }}/target/x86_64-apple-darwin/release/${{ matrix.extension }} artifacts/${{ matrix.extension }}-x86_64-apple-darwin
133+
cp ${{ matrix.path }}/target/aarch64-apple-darwin/release/${{ matrix.extension }} artifacts/${{ matrix.extension }}-aarch64-apple-darwin
134+
135+
- name: Generate changelog
136+
run: |
137+
echo "# ${{ matrix.extension }} v${{ matrix.version }}" > changelog.md
138+
echo "" >> changelog.md
139+
echo "Released on $(date +'%Y-%m-%d')" >> changelog.md
140+
echo "" >> changelog.md
141+
142+
# Add a list of changes since last release if available
143+
if gh release view ${{ matrix.extension }}-v$(echo ${{ matrix.version }} | awk -F. '{print $1"."$2"."$3-1}') &> /dev/null; then
144+
echo "## Changes since last release" >> changelog.md
145+
echo "" >> changelog.md
146+
git log --pretty=format:"* %s" ${{ matrix.extension }}-v$(echo ${{ matrix.version }} | awk -F. '{print $1"."$2"."$3-1}')..HEAD -- ${{ matrix.path }} >> changelog.md
147+
else
148+
echo "## Initial release" >> changelog.md
149+
fi
150+
env:
151+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
152+
153+
# - name: Create GitHub Release
154+
# id: create_release
155+
# uses: softprops/action-gh-release@v2
156+
# with:
157+
# tag_name: ${{ matrix.extension }}-v${{ matrix.version }}
158+
# name: ${{ matrix.extension }} v${{ matrix.version }}
159+
# body_path: ./changelog.md
160+
# draft: false
161+
# prerelease: false
162+
# files: |
163+
# artifacts/${{ matrix.extension }}-x86_64-unknown-linux-musl
164+
# artifacts/${{ matrix.extension }}-aarch64-unknown-linux-musl
165+
# artifacts/${{ matrix.extension }}-x86_64-pc-windows-msvc.exe
166+
# artifacts/${{ matrix.extension }}-x86_64-apple-darwin
167+
# artifacts/${{ matrix.extension }}-aarch64-apple-darwin
168+
# env:
169+
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
170+
171+
- name: Upload to Cloudflare R2 (Optional)
172+
if: env.CLOUDFLARE_ASSETS_ACCOUNT_ID != ''
173+
run: |
174+
# Create install script that downloads the correct binary for current platform
175+
echo '#!/bin/bash' > install-${{ matrix.extension }}
176+
echo '' >> install-${{ matrix.extension }}
177+
echo 'VERSION="${{ matrix.version }}"' >> install-${{ matrix.extension }}
178+
echo 'NAME="${{ matrix.extension }}"' >> install-${{ matrix.extension }}
179+
180+
# Add platform detection and download logic similar to Grafbase CLI installer
181+
cat << 'EOT' >> install-${{ matrix.extension }}
182+
# Platform detection
183+
PLATFORM="$(uname -s)"
184+
case $PLATFORM in
185+
Darwin)
186+
PLATFORM="apple-darwin"
187+
;;
188+
Linux)
189+
PLATFORM="unknown-linux-musl"
190+
;;
191+
MINGW*|MSYS*|CYGWIN*)
192+
PLATFORM="pc-windows-msvc.exe"
193+
;;
194+
*)
195+
echo "Unsupported platform: $PLATFORM"
196+
exit 1
197+
;;
198+
esac
199+
200+
# Architecture detection
201+
ARCHITECTURE="$(uname -m)"
202+
if [ "$ARCHITECTURE" = "x86_64" ]; then
203+
ARCHITECTURE="x86_64"
204+
elif [ "$ARCHITECTURE" = "arm64" ] || [ "$ARCHITECTURE" = "aarch64" ]; then
205+
ARCHITECTURE="aarch64"
206+
else
207+
echo "Unsupported architecture: $ARCHITECTURE"
208+
exit 1
209+
fi
210+
211+
BINARY="${NAME}-${ARCHITECTURE}-${PLATFORM}"
212+
URL="https://github.com/${{ github.repository }}/releases/download/${NAME}-v${VERSION}/${BINARY}"
213+
214+
echo "Downloading $NAME v${VERSION}..."
215+
if command -v curl > /dev/null 2>&1; then
216+
curl -fsSL "$URL" -o "$NAME"
217+
else
218+
wget -q "$URL" -O "$NAME"
219+
fi
220+
221+
chmod +x "$NAME"
222+
echo "$NAME v${VERSION} has been installed to the current directory."
223+
echo "Consider moving it to a directory in your PATH."
224+
EOT
225+
226+
# Upload to R2 if credentials are available
227+
./upload.sh install-${{ matrix.extension }}
228+
env:
229+
CLOUDFLARE_ASSETS_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ASSETS_ACCOUNT_ID }}
230+
CLOUDFLARE_ASSETS_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_ASSETS_R2_ACCESS_KEY_ID }}
231+
CLOUDFLARE_ASSETS_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_ASSETS_R2_SECRET_ACCESS_KEY }}

0 commit comments

Comments
 (0)