Skip to content

Commit 82cdb56

Browse files
committed
chore: replace release process with flow execs
1 parent f9b257a commit 82cdb56

File tree

8 files changed

+340
-216
lines changed

8 files changed

+340
-216
lines changed

.execs/container.flow

Lines changed: 145 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ tags: [development, container]
33
executables:
44
- verb: build
55
name: container
6-
description: Build the flow container image
6+
description: Build the flow container image (single-arch, local testing)
77
aliases: [docker, image]
88
exec:
99
dir: //
@@ -24,6 +24,140 @@ executables:
2424
$BUILDER build -t $IMAGE_REPO:$IMAGE_TAG .
2525
rm flow
2626

27+
- verb: build
28+
name: multiarch
29+
description: Build multi-arch container images (linux/amd64, linux/arm64) using docker buildx
30+
aliases: [buildx]
31+
exec:
32+
dir: //
33+
args:
34+
- envKey: IMAGE_REPO
35+
default: ghcr.io/flowexec/flow
36+
flag: repo
37+
- envKey: IMAGE_TAG
38+
default: latest
39+
flag: tag
40+
- envKey: DRY_RUN
41+
default: "false"
42+
flag: dry-run
43+
cmd: |
44+
set -euo pipefail
45+
46+
# Check docker buildx is available
47+
if ! docker buildx version &> /dev/null; then
48+
echo "docker buildx is not available. Please install Docker with buildx support."
49+
exit 1
50+
fi
51+
52+
# Get version info for build args
53+
GIT_COMMIT=$(git rev-parse HEAD)
54+
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
55+
VERSION="${IMAGE_TAG}"
56+
57+
# Create/use buildx builder instance
58+
BUILDER_NAME="flow-builder"
59+
if ! docker buildx inspect "$BUILDER_NAME" &> /dev/null; then
60+
echo "Creating buildx builder instance: $BUILDER_NAME"
61+
docker buildx create --name "$BUILDER_NAME" --use
62+
else
63+
docker buildx use "$BUILDER_NAME"
64+
fi
65+
66+
if [ "$DRY_RUN" = "true" ]; then
67+
echo "DRY RUN: Building multi-arch images locally (not pushing)"
68+
echo " Platforms: linux/amd64, linux/arm64"
69+
echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
70+
echo ""
71+
72+
# Build multi-arch and load to local docker (note: can only load one platform at a time)
73+
# For local testing, we'll build for the current platform only
74+
CURRENT_OS=linux
75+
CURRENT_ARCH=$(uname -m)
76+
if [ "$CURRENT_ARCH" = "x86_64" ]; then CURRENT_ARCH="amd64"; fi
77+
if [ "$CURRENT_ARCH" = "aarch64" ] || [ "$CURRENT_ARCH" = "arm64" ]; then CURRENT_ARCH="arm64"; fi
78+
79+
echo "Building for ${CURRENT_OS}/${CURRENT_ARCH} (local platform)..."
80+
81+
# First build the flow binary with version info
82+
GOOS=linux GOARCH=${CURRENT_ARCH} go build \
83+
-ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
84+
-o flow
85+
86+
# Build Docker image for local platform
87+
docker buildx build \
88+
--platform "${CURRENT_OS}/${CURRENT_ARCH}" \
89+
--tag "${IMAGE_REPO}:${IMAGE_TAG}" \
90+
--load \
91+
.
92+
93+
# Cleanup binary
94+
rm -f flow
95+
96+
echo ""
97+
echo "✓ Multi-arch image built for local platform"
98+
echo " Platform: ${CURRENT_OS}/${CURRENT_ARCH}"
99+
echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
100+
echo " Test with: docker run --rm ${IMAGE_REPO}:${IMAGE_TAG} --version"
101+
else
102+
echo "Building and pushing multi-arch images..."
103+
echo " Platforms: linux/amd64, linux/arm64"
104+
echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
105+
echo ""
106+
107+
# Build binaries for both architectures
108+
echo "Building binaries for multi-arch..."
109+
110+
# Build amd64
111+
GOOS=linux GOARCH=amd64 go build \
112+
-ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
113+
-o flow-amd64
114+
115+
# Build arm64
116+
GOOS=linux GOARCH=arm64 go build \
117+
-ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
118+
-o flow-arm64
119+
120+
# Create temporary Dockerfile that uses TARGETARCH for multi-arch builds
121+
TEMP_DOCKERFILE=/tmp/Dockerfile.multiarch.$$
122+
123+
echo "FROM --platform=\$TARGETPLATFORM golang:1.25.1-bookworm" > "$TEMP_DOCKERFILE"
124+
echo "" >> "$TEMP_DOCKERFILE"
125+
echo "ARG TARGETARCH" >> "$TEMP_DOCKERFILE"
126+
echo 'ENV DISABLE_FLOW_INTERACTIVE="true"' >> "$TEMP_DOCKERFILE"
127+
echo "" >> "$TEMP_DOCKERFILE"
128+
echo "# TODO: replace with examples repo" >> "$TEMP_DOCKERFILE"
129+
echo 'ENV WORKSPACE="flow"' >> "$TEMP_DOCKERFILE"
130+
echo 'ENV REPO="https://github.com/flowexec/flow.git"' >> "$TEMP_DOCKERFILE"
131+
echo 'ENV BRANCH=""' >> "$TEMP_DOCKERFILE"
132+
echo "" >> "$TEMP_DOCKERFILE"
133+
echo "WORKDIR /workspaces" >> "$TEMP_DOCKERFILE"
134+
echo "" >> "$TEMP_DOCKERFILE"
135+
echo "# Copy the appropriate binary based on architecture" >> "$TEMP_DOCKERFILE"
136+
echo 'COPY flow-${TARGETARCH} /usr/bin/flow' >> "$TEMP_DOCKERFILE"
137+
echo "" >> "$TEMP_DOCKERFILE"
138+
echo 'RUN if [ -z "$BRANCH" ]; then git clone $REPO .; else git clone -b $BRANCH $REPO .; fi' >> "$TEMP_DOCKERFILE"
139+
echo 'RUN flow workspace create $WORKSPACE . --set' >> "$TEMP_DOCKERFILE"
140+
echo "" >> "$TEMP_DOCKERFILE"
141+
echo 'ENTRYPOINT ["flow"]' >> "$TEMP_DOCKERFILE"
142+
echo 'CMD ["--version"]' >> "$TEMP_DOCKERFILE"
143+
144+
# Build and push multi-arch image
145+
docker buildx build \
146+
--platform linux/amd64,linux/arm64 \
147+
--tag "${IMAGE_REPO}:${IMAGE_TAG}" \
148+
--tag "${IMAGE_REPO}:latest" \
149+
--push \
150+
--file "$TEMP_DOCKERFILE" \
151+
.
152+
153+
# Cleanup
154+
rm -f flow-amd64 flow-arm64 "$TEMP_DOCKERFILE"
155+
156+
echo ""
157+
echo "✓ Multi-arch images pushed to ${IMAGE_REPO}"
158+
echo " Tags: ${IMAGE_TAG}, latest"
159+
fi
160+
27161
- verb: run
28162
name: container
29163
description: Run the flow container image
@@ -63,7 +197,7 @@ executables:
63197

64198
- verb: push
65199
name: container
66-
description: Push the flow container image to the registry
200+
description: Push the flow container image to the registry (use with build multiarch for production)
67201
aliases: [image, docker]
68202
exec:
69203
dir: //
@@ -77,6 +211,15 @@ executables:
77211
- envKey: IMAGE_TAG
78212
default: latest
79213
flag: tag
214+
- envKey: DRY_RUN
215+
default: "false"
216+
flag: dry-run
80217
cmd: |
218+
if [ "$DRY_RUN" = "true" ]; then
219+
echo "DRY RUN: Would push ${IMAGE_REPO}:${IMAGE_TAG}"
220+
echo "Skipping actual push to registry"
221+
exit 0
222+
fi
223+
81224
echo "pushing container image..."
82225
$BUILDER push $IMAGE_REPO:$IMAGE_TAG

.execs/release.flow

Lines changed: 152 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,34 @@
11
# yaml-language-server: $schema=https://flowexec.io/schemas/flowfile_schema.json
22
tags: [development, test]
33
executables:
4-
- verb: create
4+
- verb: build
55
name: snapshot
6-
description: Create a snapshot release locally (skips Docker builds by default)
7-
aliases: [release, snap]
6+
description: Create a local snapshot release (binaries + archives, no publish)
7+
aliases: [release, snap, test-release]
88
exec:
99
dir: //
10-
params:
11-
- envKey: SKIP_DOCKER
12-
text: "true"
1310
cmd: |
11+
set -euo pipefail
1412
if ! command -v goreleaser &> /dev/null; then
15-
echo "goreleaser is not installed. Please install it first."
13+
echo "goreleaser is not installed. Run 'flow install tools' first."
1614
exit 1
1715
fi
1816

19-
SKIP_FLAG=""
20-
if [ "$SKIP_DOCKER" = "true" ]; then
21-
echo "Creating snapshot release (skipping Docker builds)..."
22-
SKIP_FLAG="--skip=docker"
23-
else
24-
echo "Creating snapshot release (including Docker builds)..."
25-
fi
17+
echo "Creating snapshot release (local dry-run)..."
18+
echo " - Builds binaries for all platforms"
19+
echo " - Creates archives with completions"
20+
echo " - Generates changelog"
21+
echo " - Does NOT push to GitHub or registries"
22+
echo ""
2623

27-
goreleaser release --snapshot --clean $SKIP_FLAG
24+
goreleaser release --snapshot --clean
2825

2926
echo ""
30-
echo "Snapshot build complete!"
27+
echo "Snapshot build complete!"
3128
echo ""
3229
echo "Binaries built for:"
3330
ls -1 dist/ | grep -E "^flow_.*_(linux|darwin)_(amd64|arm64)" | sed 's/^/ - /'
3431

35-
if [ "$SKIP_DOCKER" = "false" ]; then
36-
echo ""
37-
echo "Docker images built:"
38-
echo " - ghcr.io/flowexec/flow:{{ .Tag }}"
39-
echo " - ghcr.io/flowexec/flow:latest"
40-
echo ""
41-
echo "Test Docker image locally:"
42-
echo " docker run --rm ghcr.io/flowexec/flow:latest --version"
43-
fi
44-
4532
echo ""
4633
echo "Test your platform's binary:"
4734
CURRENT_OS=$(uname -s | tr '[:upper:]' '[:lower:]')
@@ -56,14 +43,152 @@ executables:
5643
${BINARY_DIR}/flow --version
5744
fi
5845

46+
- verb: build
47+
name: artifacts
48+
description: Build release artifacts (binaries, archives, changelog) without publishing
49+
aliases: [binaries]
50+
exec:
51+
dir: //
52+
args:
53+
- envKey: VERSION
54+
flag: version
55+
required: false
56+
cmd: |
57+
set -euo pipefail
58+
if ! command -v goreleaser &> /dev/null; then
59+
echo "goreleaser is not installed. Run 'flow install tools' first."
60+
exit 1
61+
fi
62+
63+
if [ -n "${VERSION:-}" ]; then
64+
echo "Building release artifacts for version: ${VERSION}"
65+
echo "Note: This is a DRY RUN. Use 'flow publish release' in CI for actual releases."
66+
else
67+
echo "Building release artifacts from current state"
68+
echo "Note: This is a DRY RUN (snapshot mode)"
69+
fi
70+
echo ""
71+
72+
goreleaser release --snapshot --clean --skip=publish
73+
74+
echo ""
75+
echo "✓ Release artifacts built in dist/"
76+
echo ""
77+
echo "To test Docker multi-arch build locally:"
78+
echo " flow build multiarch --dry-run"
79+
80+
- verb: build
81+
name: docker-local
82+
description: Build Docker image locally for current platform (dry-run, no push)
83+
aliases: [docker-test]
84+
exec:
85+
dir: //
86+
args:
87+
- envKey: IMAGE_TAG
88+
default: dev
89+
flag: tag
90+
cmd: |
91+
set -euo pipefail
92+
echo "Building Docker image for local platform (dry-run)..."
93+
echo ""
94+
95+
flow build multiarch -p IMAGE_REPO=ghcr.io/flowexec/flow -p IMAGE_TAG="${IMAGE_TAG}" -p DRY_RUN=true
96+
97+
echo ""
98+
echo "✓ Local Docker build complete"
99+
echo " To publish multi-arch: flow publish docker -p IMAGE_TAG=${IMAGE_TAG}"
100+
101+
- verb: publish
102+
name: docker
103+
aliases: [image]
104+
description: Publish multi-arch Docker images to ghcr.io (CI only)
105+
visibility: private
106+
exec:
107+
dir: //
108+
args:
109+
- envKey: IMAGE_TAG
110+
flag: tag
111+
required: true
112+
- envKey: REGISTRY
113+
default: ghcr.io
114+
flag: registry
115+
cmd: |
116+
set -euo pipefail
117+
118+
echo "Publishing multi-arch Docker images to ${REGISTRY}..."
119+
echo " Tag: ${IMAGE_TAG}"
120+
echo ""
121+
122+
if [ -z "${CI:-}" ]; then
123+
echo "⚠️ WARNING: This should typically only be run in CI"
124+
echo " For local testing, use: flow build docker-local"
125+
echo ""
126+
read -p "Continue with publish? (y/N) " -n 1 -r
127+
echo
128+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
129+
echo "Publish cancelled"
130+
exit 1
131+
fi
132+
fi
133+
134+
flow build multiarch -p IMAGE_REPO=${REGISTRY}/flowexec/flow -p IMAGE_TAG="${IMAGE_TAG}" -p DRY_RUN=false
135+
136+
echo ""
137+
echo "✓ Docker images published"
138+
echo " ${REGISTRY}/flowexec/flow:${IMAGE_TAG}"
139+
echo " ${REGISTRY}/flowexec/flow:latest"
140+
141+
- verb: publish
142+
name: release
143+
description: Full release pipeline (artifacts + docker + GitHub) - CI only
144+
visibility: private
145+
serial:
146+
dir: //
147+
failFast: true
148+
args:
149+
- envKey: VERSION
150+
flag: version
151+
required: true
152+
execs:
153+
- name: Validate CI environment
154+
cmd: |
155+
if [ -z "${CI:-}" ]; then
156+
echo "❌ ERROR: This executable must only be run in CI"
157+
echo " For local testing, use:"
158+
echo " - flow build snapshot # Test binaries/archives"
159+
echo " - flow build docker-local # Test Docker builds"
160+
exit 1
161+
fi
162+
echo "Starting full release pipeline for version ${VERSION}..."
163+
- name: Build and publish release artifacts
164+
cmd: |
165+
set -euo pipefail
166+
if ! command -v goreleaser &> /dev/null; then
167+
echo "goreleaser is not installed"
168+
exit 1
169+
fi
170+
echo "Building and publishing release artifacts with goreleaser..."
171+
goreleaser release --clean
172+
- name: Publish multi-arch Docker images
173+
ref: publish docker
174+
args:
175+
- IMAGE_TAG=${VERSION}
176+
- name: Release complete
177+
cmd: |
178+
echo ""
179+
echo "✓ Release ${VERSION} complete!"
180+
echo " - Binaries published to GitHub Releases"
181+
echo " - Homebrew tap updated"
182+
echo " - Docker images published to ghcr.io"
183+
59184
- verb: check
60185
name: release
61186
description: Check goreleaser configuration without building
62187
exec:
63188
dir: //
64189
cmd: |
65190
if ! command -v goreleaser &> /dev/null; then
66-
echo "goreleaser is not installed. Please install it first."
191+
echo "goreleaser is not installed. Run 'flow install tools' first."
67192
exit 1
68193
fi
69194

0 commit comments

Comments
 (0)