Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,45 @@ jobs:
name: ui-build
path: src/http/ui/dist

- name: Install UPX
run: |
sudo apt-get update
sudo apt-get install -y upx-ucl

- name: Build using Makefile
run: |
make linux-${{ matrix.arch }} VERSION="$VERSION"

- name: Compress with UPX
run: |
ARCH="${{ matrix.arch }}"
BINARY_PATH="out/linux-${ARCH}/${{ env.BINARY_NAME }}"

if [ -f "$BINARY_PATH" ]; then
echo "Compressing $BINARY_PATH with UPX..."
upx --ultra-brute --lzma "$BINARY_PATH" -o "${BINARY_PATH}.upx"

Comment on lines +123 to +124
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--ultra-brute --lzma can make the release workflow substantially slower across the full arch matrix. Unless maximum compression is required, consider a faster default (e.g., --best) and/or make the compression level configurable (workflow input/env) so you can trade off size vs. build time.

Copilot uses AI. Check for mistakes.
# Test compressed binary
if upx -t "${BINARY_PATH}.upx"; then
echo "UPX compression successful, replacing original binary"
mv "${BINARY_PATH}.upx" "$BINARY_PATH"
else
echo "UPX test failed, keeping original binary"
Comment on lines +123 to +130
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step intends to keep the original binary if UPX fails, but with GitHub Actions’ default bash -e behavior the command upx --ultra-brute --lzma ... will fail the step immediately on any non-zero exit code (e.g., unsupported arch/format), and the fallback logic below won’t run. Wrap the compression command in an if upx ...; then ... else ... block (or otherwise handle the exit status) so the fallback actually works.

Suggested change
upx --ultra-brute --lzma "$BINARY_PATH" -o "${BINARY_PATH}.upx"
# Test compressed binary
if upx -t "${BINARY_PATH}.upx"; then
echo "UPX compression successful, replacing original binary"
mv "${BINARY_PATH}.upx" "$BINARY_PATH"
else
echo "UPX test failed, keeping original binary"
if upx --ultra-brute --lzma "$BINARY_PATH" -o "${BINARY_PATH}.upx"; then
# Test compressed binary
if upx -t "${BINARY_PATH}.upx"; then
echo "UPX compression successful, replacing original binary"
mv "${BINARY_PATH}.upx" "$BINARY_PATH"
else
echo "UPX test failed, keeping original binary"
rm -f "${BINARY_PATH}.upx"
fi
else
echo "UPX compression failed (possibly unsupported arch/format), keeping original binary"

Copilot uses AI. Check for mistakes.
rm -f "${BINARY_PATH}.upx"
fi
else
echo "Binary not found at $BINARY_PATH"
exit 1
fi

- name: Repackage with compressed binary
run: |
ARCH="${{ matrix.arch }}"
cd out/linux-${ARCH}
tar -czf "../assets/${{ env.BINARY_NAME }}-linux-${ARCH}.tar.gz" "${{ env.BINARY_NAME }}"
cd ../assets
sha256sum "${{ env.BINARY_NAME }}-linux-${ARCH}.tar.gz" > "${{ env.BINARY_NAME }}-linux-${ARCH}.tar.gz.sha256"

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
Expand Down
21 changes: 13 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,26 @@ RUN COMMIT=$(echo "docker" ) && \
GOARM=${TARGETVARIANT#v} \
CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go -C src build \
-trimpath \
-buildvcs=false \
-ldflags "-s -w -X main.Version=${VERSION} -X main.Commit=${COMMIT} -X main.Date=${DATE}" \
-o /b4

# Stage 2.5: UPX compression
FROM --platform=$TARGETPLATFORM alpine:3.23.3 AS upx-compressor
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UPX stage is pinned to --platform=$TARGETPLATFORM, which means during cross-platform builds (e.g., building linux/arm64 on an amd64 runner) the upx binary itself will run under QEMU emulation. That typically slows builds significantly and can fail if emulation isn’t available. Consider running the compressor stage on $BUILDPLATFORM (tooling runs native) while still compressing the target-arch /b4 output.

Suggested change
FROM --platform=$TARGETPLATFORM alpine:3.23.3 AS upx-compressor
FROM --platform=$BUILDPLATFORM alpine:3.23.3 AS upx-compressor

Copilot uses AI. Check for mistakes.

RUN apk add --no-cache upx

COPY --from=go-builder /b4 /b4
RUN upx --ultra-brute --lzma /b4 -o /b4.upx && upx -t /b4.upx
Comment on lines +43 to +46
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upx --ultra-brute --lzma is extremely CPU-intensive and can add a large amount of time to Docker builds (especially under QEMU when cross-building). Consider switching to a less expensive preset (e.g., --best) or making the compression level configurable via a build arg so release builds can opt into ultra-brute when needed.

Suggested change
RUN apk add --no-cache upx
COPY --from=go-builder /b4 /b4
RUN upx --ultra-brute --lzma /b4 -o /b4.upx && upx -t /b4.upx
ARG UPX_FLAGS="--best"
RUN apk add --no-cache upx
COPY --from=go-builder /b4 /b4
RUN upx ${UPX_FLAGS} /b4 -o /b4.upx && upx -t /b4.upx

Copilot uses AI. Check for mistakes.

# Stage 3: Runtime image
FROM alpine:3.23.3

RUN apk add --no-cache \
iptables \
ip6tables \
nftables \
kmod \
iproute2 \
tzdata

COPY --from=go-builder /b4 /usr/local/bin/b4
iptables ip6tables nftables kmod iproute2 tzdata \
&& rm -rf /var/cache/apk/*

COPY --from=upx-compressor /b4.upx /usr/local/bin/b4

VOLUME /etc/b4
EXPOSE 7000
Expand Down