faster, cheaper (pick two): improve CI workflow and switch to free github runner (#5702)

Co-authored-by: Douwe Osinga <douwe@block.xyz>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Jack Amadeo
2025-11-14 09:58:57 -08:00
committed by GitHub
parent bbac7d6250
commit d4f66f4855
8 changed files with 127 additions and 214 deletions
+7 -19
View File
@@ -78,29 +78,17 @@ jobs:
if: matrix.use-cross if: matrix.use-cross
run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross
# Cache Cargo registry and git dependencies for Windows builds - name: Cache Cargo artifacts (Linux/macOS)
- name: Cache Cargo registry (Windows) if: matrix.use-cross
if: matrix.use-docker uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f
with: with:
path: | key: ${{ matrix.architecture }}-${{ matrix.target-suffix }}
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-
# Cache compiled dependencies (target/release/deps) for Windows builds - name: Cache Cargo artifacts (Windows)
- name: Cache Cargo build (Windows)
if: matrix.use-docker if: matrix.use-docker
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2
with: with:
path: target key: ${{ matrix.architecture }}-${{ matrix.target-suffix }}
key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-${{ hashFiles('rust-toolchain.toml') }}
restore-keys: |
${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-
${{ runner.os }}-cargo-build-release-
- name: Build CLI (Linux/macOS) - name: Build CLI (Linux/macOS)
if: matrix.use-cross if: matrix.use-cross
+3 -22
View File
@@ -63,29 +63,10 @@ jobs:
cd ui/desktop cd ui/desktop
npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version
- name: Cache Cargo registry - name: Cache Rust dependencies
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2
with: with:
path: ~/.cargo/registry key: intel
key: ${{ runner.os }}-intel-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-intel-cargo-registry-
- name: Cache Cargo index
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3
with:
path: ~/.cargo/index
key: ${{ runner.os }}-intel-cargo-index
restore-keys: |
${{ runner.os }}-intel-cargo-index
- name: Cache Cargo build
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3
with:
path: target
key: ${{ runner.os }}-intel-cargo-build-release-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-intel-cargo-build-release-
- name: Build goose-server for Intel macOS (x86_64) - name: Build goose-server for Intel macOS (x86_64)
+6 -13
View File
@@ -87,17 +87,10 @@ jobs:
- name: Install cross - name: Install cross
run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross run: source ./bin/activate-hermit && cargo install cross --git https://github.com/cross-rs/cross
- name: Cache Cargo artifacts - name: Cache Rust dependencies
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2
with: with:
path: | key: linux
${{ env.CARGO_HOME }}/bin/
${{ env.CARGO_HOME }}/registry/index/
${{ env.CARGO_HOME }}/registry/cache/
${{ env.CARGO_HOME }}/git/db/
key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-release-
- name: Build goosed binary - name: Build goosed binary
env: env:
@@ -164,21 +157,21 @@ jobs:
find ui/desktop/out/ -name "*.deb" -o -name "*.rpm" -exec ls -lh {} \; find ui/desktop/out/ -name "*.deb" -o -name "*.rpm" -exec ls -lh {} \;
- name: Upload .deb package - name: Upload .deb package
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with: with:
name: Goose-linux-x64-deb name: Goose-linux-x64-deb
path: ui/desktop/out/make/deb/x64/*.deb path: ui/desktop/out/make/deb/x64/*.deb
if-no-files-found: error if-no-files-found: error
- name: Upload .rpm package - name: Upload .rpm package
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with: with:
name: Goose-linux-x64-rpm name: Goose-linux-x64-rpm
path: ui/desktop/out/make/rpm/x64/*.rpm path: ui/desktop/out/make/rpm/x64/*.rpm
if-no-files-found: error if-no-files-found: error
- name: Upload combined Linux packages - name: Upload combined Linux packages
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with: with:
name: Goose-linux-x64 name: Goose-linux-x64
path: | path: |
+35 -65
View File
@@ -1,7 +1,7 @@
name: "Bundle Desktop (Windows)" name: "Bundle Desktop (Windows)"
on: on:
# push: # push:
# branches: [ "main" ] # branches: [ "main" ]
# pull_request: # pull_request:
# branches: [ "main" ] # branches: [ "main" ]
@@ -41,15 +41,12 @@ jobs:
runs-on: ubuntu-latest # Use Ubuntu for cross-compilation runs-on: ubuntu-latest # Use Ubuntu for cross-compilation
steps: steps:
# 1) Check out source
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4
with: with:
# Only pass ref if it's explicitly set, otherwise let checkout action use its default behavior
ref: ${{ inputs.ref != '' && inputs.ref || '' }} ref: ${{ inputs.ref != '' && inputs.ref || '' }}
fetch-depth: 0 fetch-depth: 0
# 2) Configure AWS credentials for code signing
- name: Configure AWS credentials - name: Configure AWS credentials
if: inputs.signing && inputs.signing == true if: inputs.signing && inputs.signing == true
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # ratchet:aws-actions/configure-aws-credentials@v4 uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # ratchet:aws-actions/configure-aws-credentials@v4
@@ -57,13 +54,11 @@ jobs:
role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.WINDOW_SIGNING_ROLE || secrets.WINDOW_SIGNING_ROLE_TAG }} role-to-assume: ${{ github.ref == 'refs/heads/main' && secrets.WINDOW_SIGNING_ROLE || secrets.WINDOW_SIGNING_ROLE_TAG }}
aws-region: us-west-2 aws-region: us-west-2
# 2) Set up Node.js
- name: Set up Node.js - name: Set up Node.js
uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # pin@v3 uses: actions/setup-node@1a4442cacd436585916779262731d5b162bc6ec7 # pin@v3
with: with:
node-version: 22 node-version: 22
# 3) Cache dependencies
- name: Cache node_modules - name: Cache node_modules
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3
with: with:
@@ -75,36 +70,18 @@ jobs:
restore-keys: | restore-keys: |
windows-npm-cache-v1-${{ runner.os }}-node22- windows-npm-cache-v1-${{ runner.os }}-node22-
# Cache Cargo registry and git dependencies - name: Cache Rust dependencies
- name: Cache Cargo registry uses: Swatinem/rust-cache@v2
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f
with: with:
path: | key: windows
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-
# Cache compiled dependencies (target/release/deps)
- name: Cache Cargo build
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f
with:
path: target
key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-${{ hashFiles('rust-toolchain.toml') }}
restore-keys: |
${{ runner.os }}-cargo-build-release-${{ hashFiles('Cargo.lock') }}-
${{ runner.os }}-cargo-build-release-
# 4) Build Rust for Windows using Docker (cross-compilation with enhanced caching)
- name: Build Windows executable using Docker cross-compilation with enhanced caching - name: Build Windows executable using Docker cross-compilation with enhanced caching
run: | run: |
echo "🚀 Building Windows executable with enhanced GitHub Actions caching..." echo "🚀 Building Windows executable with enhanced GitHub Actions caching..."
# Create cache directories # Create cache directories
mkdir -p ~/.cargo/registry ~/.cargo/git mkdir -p ~/.cargo/registry ~/.cargo/git
# Use enhanced caching with GitHub Actions cache mounts # Use enhanced caching with GitHub Actions cache mounts
docker run --rm \ docker run --rm \
-v "$(pwd)":/usr/src/myapp \ -v "$(pwd)":/usr/src/myapp \
@@ -117,7 +94,7 @@ jobs:
echo '=== Setting up Rust environment with caching ===' echo '=== Setting up Rust environment with caching ==='
export CARGO_HOME=/usr/local/cargo export CARGO_HOME=/usr/local/cargo
export PATH=/usr/local/cargo/bin:\$PATH export PATH=/usr/local/cargo/bin:\$PATH
# Check if Windows target is already installed in cache # Check if Windows target is already installed in cache
if rustup target list --installed | grep -q x86_64-pc-windows-gnu; then if rustup target list --installed | grep -q x86_64-pc-windows-gnu; then
echo '✅ Windows cross-compilation target already installed' echo '✅ Windows cross-compilation target already installed'
@@ -125,11 +102,11 @@ jobs:
echo '📦 Installing Windows cross-compilation target...' echo '📦 Installing Windows cross-compilation target...'
rustup target add x86_64-pc-windows-gnu rustup target add x86_64-pc-windows-gnu
fi fi
echo '=== Setting up build dependencies ===' echo '=== Setting up build dependencies ==='
apt-get update apt-get update
apt-get install -y mingw-w64 protobuf-compiler cmake time apt-get install -y mingw-w64 protobuf-compiler cmake time
echo '=== Setting up cross-compilation environment ===' echo '=== Setting up cross-compilation environment ==='
export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc export CC_x86_64_pc_windows_gnu=x86_64-w64-mingw32-gcc
export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++ export CXX_x86_64_pc_windows_gnu=x86_64-w64-mingw32-g++
@@ -137,7 +114,7 @@ jobs:
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
export PKG_CONFIG_ALLOW_CROSS=1 export PKG_CONFIG_ALLOW_CROSS=1
export PROTOC=/usr/bin/protoc export PROTOC=/usr/bin/protoc
echo '=== Optimized Cargo configuration ===' echo '=== Optimized Cargo configuration ==='
mkdir -p .cargo mkdir -p .cargo
echo '[build]' > .cargo/config.toml echo '[build]' > .cargo/config.toml
@@ -159,7 +136,7 @@ jobs:
echo '' >> .cargo/config.toml echo '' >> .cargo/config.toml
echo '[registries.crates-io]' >> .cargo/config.toml echo '[registries.crates-io]' >> .cargo/config.toml
echo 'protocol = \"sparse\"' >> .cargo/config.toml echo 'protocol = \"sparse\"' >> .cargo/config.toml
echo '=== Building with cached dependencies ===' echo '=== Building with cached dependencies ==='
# Check if we have cached build artifacts # Check if we have cached build artifacts
if [ -d target/x86_64-pc-windows-gnu/release/deps ] && [ \"\$(ls -A target/x86_64-pc-windows-gnu/release/deps)\" ]; then if [ -d target/x86_64-pc-windows-gnu/release/deps ] && [ \"\$(ls -A target/x86_64-pc-windows-gnu/release/deps)\" ]; then
@@ -169,51 +146,50 @@ jobs:
echo '🔨 No cached artifacts found, performing full build...' echo '🔨 No cached artifacts found, performing full build...'
CARGO_INCREMENTAL=0 CARGO_INCREMENTAL=0
fi fi
echo '🔨 Building Windows executable...' echo '🔨 Building Windows executable...'
CARGO_INCREMENTAL=\$CARGO_INCREMENTAL \ CARGO_INCREMENTAL=\$CARGO_INCREMENTAL \
CARGO_NET_RETRY=3 \ CARGO_NET_RETRY=3 \
CARGO_HTTP_TIMEOUT=60 \ CARGO_HTTP_TIMEOUT=60 \
RUST_BACKTRACE=1 \ RUST_BACKTRACE=1 \
cargo build --release --target x86_64-pc-windows-gnu --jobs 4 cargo build --release --target x86_64-pc-windows-gnu --jobs 4
echo '=== Copying Windows runtime DLLs ===' echo '=== Copying Windows runtime DLLs ==='
GCC_DIR=\$(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1) GCC_DIR=\$(ls -d /usr/lib/gcc/x86_64-w64-mingw32/*/ | head -n 1)
cp \"\$GCC_DIR/libstdc++-6.dll\" target/x86_64-pc-windows-gnu/release/ cp \"\$GCC_DIR/libstdc++-6.dll\" target/x86_64-pc-windows-gnu/release/
cp \"\$GCC_DIR/libgcc_s_seh-1.dll\" target/x86_64-pc-windows-gnu/release/ cp \"\$GCC_DIR/libgcc_s_seh-1.dll\" target/x86_64-pc-windows-gnu/release/
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll target/x86_64-pc-windows-gnu/release/ cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll target/x86_64-pc-windows-gnu/release/
echo '✅ Build completed successfully!' echo '✅ Build completed successfully!'
ls -la target/x86_64-pc-windows-gnu/release/ ls -la target/x86_64-pc-windows-gnu/release/
" "
# Verify build succeeded # Verify build succeeded
if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then
echo "❌ Windows binary not found." echo "❌ Windows binary not found."
ls -la ./target/x86_64-pc-windows-gnu/release/ || echo "Release directory doesn't exist" ls -la ./target/x86_64-pc-windows-gnu/release/ || echo "Release directory doesn't exist"
exit 1 exit 1
fi fi
echo "✅ Windows binary found!" echo "✅ Windows binary found!"
ls -la ./target/x86_64-pc-windows-gnu/release/goosed.exe ls -la ./target/x86_64-pc-windows-gnu/release/goosed.exe
ls -la ./target/x86_64-pc-windows-gnu/release/*.dll ls -la ./target/x86_64-pc-windows-gnu/release/*.dll
# 5) Prepare Windows binary and DLLs
- name: Prepare Windows binary and DLLs - name: Prepare Windows binary and DLLs
run: | run: |
if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then if [ ! -f "./target/x86_64-pc-windows-gnu/release/goosed.exe" ]; then
echo "Windows binary not found." echo "Windows binary not found."
exit 1 exit 1
fi fi
echo "Cleaning destination directory..." echo "Cleaning destination directory..."
rm -rf ./ui/desktop/src/bin rm -rf ./ui/desktop/src/bin
mkdir -p ./ui/desktop/src/bin mkdir -p ./ui/desktop/src/bin
echo "Copying Windows binary and DLLs..." echo "Copying Windows binary and DLLs..."
cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/ cp -f ./target/x86_64-pc-windows-gnu/release/goosed.exe ./ui/desktop/src/bin/
cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/ cp -f ./target/x86_64-pc-windows-gnu/release/*.dll ./ui/desktop/src/bin/
# Copy Windows platform files (tools, scripts, etc.) # Copy Windows platform files (tools, scripts, etc.)
if [ -d "./ui/desktop/src/platform/windows/bin" ]; then if [ -d "./ui/desktop/src/platform/windows/bin" ]; then
echo "Copying Windows platform files..." echo "Copying Windows platform files..."
@@ -222,7 +198,7 @@ jobs:
cp -f "$file" ./ui/desktop/src/bin/ cp -f "$file" ./ui/desktop/src/bin/
fi fi
done done
if [ -d "./ui/desktop/src/platform/windows/bin/goose-npm" ]; then if [ -d "./ui/desktop/src/platform/windows/bin/goose-npm" ]; then
echo "Setting up npm environment..." echo "Setting up npm environment..."
rsync -a --delete ./ui/desktop/src/platform/windows/bin/goose-npm/ ./ui/desktop/src/bin/goose-npm/ rsync -a --delete ./ui/desktop/src/platform/windows/bin/goose-npm/ ./ui/desktop/src/bin/goose-npm/
@@ -230,56 +206,53 @@ jobs:
echo "Windows-specific files copied successfully" echo "Windows-specific files copied successfully"
fi fi
# 6) Install & build UI desktop
- name: Build desktop UI with npm - name: Build desktop UI with npm
run: | run: |
cd ui/desktop cd ui/desktop
npm install npm install
npm run bundle:windows npm run bundle:windows
# 7) Copy exe/dll to final out folder and prepare flat distribution
- name: Copy exe/dll to final out folder and prepare flat distribution - name: Copy exe/dll to final out folder and prepare flat distribution
run: | run: |
cd ui/desktop cd ui/desktop
mkdir -p ./out/Goose-win32-x64/resources/bin mkdir -p ./out/Goose-win32-x64/resources/bin
rsync -av src/bin/ out/Goose-win32-x64/resources/bin/ rsync -av src/bin/ out/Goose-win32-x64/resources/bin/
# Create flat distribution structure # Create flat distribution structure
mkdir -p ./dist-windows mkdir -p ./dist-windows
cp -r ./out/Goose-win32-x64/* ./dist-windows/ cp -r ./out/Goose-win32-x64/* ./dist-windows/
# Verify the final structure # Verify the final structure
echo "📋 Final flat distribution structure:" echo "📋 Final flat distribution structure:"
ls -la ./dist-windows/ ls -la ./dist-windows/
echo "📋 Binary files in resources/bin:" echo "📋 Binary files in resources/bin:"
ls -la ./dist-windows/resources/bin/ ls -la ./dist-windows/resources/bin/
# 8) Sign Windows executables with jsign + AWS KMS
- name: Sign Windows executables with jsign + AWS KMS - name: Sign Windows executables with jsign + AWS KMS
if: inputs.signing && inputs.signing == true if: inputs.signing && inputs.signing == true
run: | run: |
set -exuo pipefail set -exuo pipefail
echo "🔐 Starting Windows code signing with jsign + AWS KMS..." echo "🔐 Starting Windows code signing with jsign + AWS KMS..."
# Create certificate file from secret # Create certificate file from secret
echo "📝 Creating certificate file from GitHub secret..." echo "📝 Creating certificate file from GitHub secret..."
echo "${{ secrets.WINDOWS_CODESIGN_CERTIFICATE }}" > block-codesign-cert.pem echo "${{ secrets.WINDOWS_CODESIGN_CERTIFICATE }}" > block-codesign-cert.pem
# Install Java (required for jsign) # Install Java (required for jsign)
echo "☕ Installing Java runtime..." echo "☕ Installing Java runtime..."
sudo apt-get update sudo apt-get update
sudo apt-get install -y openjdk-11-jre-headless osslsigncode sudo apt-get install -y openjdk-11-jre-headless osslsigncode
# Download jsign # Download jsign
echo "📥 Downloading jsign..." echo "📥 Downloading jsign..."
wget -q https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O jsign.jar wget -q https://github.com/ebourg/jsign/releases/download/6.0/jsign-6.0.jar -O jsign.jar
echo "05ca18d4ab7b8c2183289b5378d32860f0ea0f3bdab1f1b8cae5894fb225fa8a jsign.jar" | sha256sum -c echo "05ca18d4ab7b8c2183289b5378d32860f0ea0f3bdab1f1b8cae5894fb225fa8a jsign.jar" | sha256sum -c
# Sign the main Electron executable (Goose.exe) # Sign the main Electron executable (Goose.exe)
echo "🔐 Signing main Electron executable: Goose.exe" echo "🔐 Signing main Electron executable: Goose.exe"
cd ui/desktop/dist-windows/ cd ui/desktop/dist-windows/
java -jar ${GITHUB_WORKSPACE}/jsign.jar \ java -jar ${GITHUB_WORKSPACE}/jsign.jar \
--storetype AWS \ --storetype AWS \
--keystore us-west-2 \ --keystore us-west-2 \
@@ -293,11 +266,11 @@ jobs:
osslsigncode verify Goose.exe osslsigncode verify Goose.exe
echo "✅ Main executable Goose.exe signed successfully" echo "✅ Main executable Goose.exe signed successfully"
# Sign the backend executable (goosed.exe) # Sign the backend executable (goosed.exe)
echo "🔐 Signing backend executable: goosed.exe" echo "🔐 Signing backend executable: goosed.exe"
cd resources/bin/ cd resources/bin/
java -jar ${GITHUB_WORKSPACE}/jsign.jar \ java -jar ${GITHUB_WORKSPACE}/jsign.jar \
--storetype AWS \ --storetype AWS \
--keystore us-west-2 \ --keystore us-west-2 \
@@ -319,11 +292,10 @@ jobs:
sha256sum Goose.exe sha256sum Goose.exe
ls -la resources/bin/goosed.exe ls -la resources/bin/goosed.exe
sha256sum resources/bin/goosed.exe sha256sum resources/bin/goosed.exe
# Clean up certificate file # Clean up certificate file
rm -f ${GITHUB_WORKSPACE}/block-codesign-cert.pem rm -f ${GITHUB_WORKSPACE}/block-codesign-cert.pem
# 9) Verify signed executables are in final distribution
- name: Verify signed executables are in final distribution - name: Verify signed executables are in final distribution
if: inputs.signing && inputs.signing == true if: inputs.signing && inputs.signing == true
run: | run: |
@@ -332,29 +304,27 @@ jobs:
ls -la ui/desktop/dist-windows/Goose.exe ls -la ui/desktop/dist-windows/Goose.exe
osslsigncode verify ui/desktop/dist-windows/Goose.exe osslsigncode verify ui/desktop/dist-windows/Goose.exe
echo "✅ Main executable signature verification passed" echo "✅ Main executable signature verification passed"
echo "Backend executable:" echo "Backend executable:"
ls -la ui/desktop/dist-windows/resources/bin/goosed.exe ls -la ui/desktop/dist-windows/resources/bin/goosed.exe
osslsigncode verify ui/desktop/dist-windows/resources/bin/goosed.exe osslsigncode verify ui/desktop/dist-windows/resources/bin/goosed.exe
echo "✅ Backend executable signature verification passed" echo "✅ Backend executable signature verification passed"
# 10) Create Windows zip package
- name: Create Windows zip package - name: Create Windows zip package
run: | run: |
cd ui/desktop cd ui/desktop
echo "📦 Creating Windows zip package..." echo "📦 Creating Windows zip package..."
# Create a zip file from the dist-windows directory # Create a zip file from the dist-windows directory
zip -r "Goose-win32-x64.zip" dist-windows/ zip -r "Goose-win32-x64.zip" dist-windows/
echo "✅ Windows zip package created:" echo "✅ Windows zip package created:"
ls -la Goose-win32-x64.zip ls -la Goose-win32-x64.zip
# Also create the zip in the expected output structure for consistency # Also create the zip in the expected output structure for consistency
mkdir -p out/Goose-win32-x64/ mkdir -p out/Goose-win32-x64/
cp Goose-win32-x64.zip out/Goose-win32-x64/ cp Goose-win32-x64.zip out/Goose-win32-x64/
# 11) Upload the final Windows build
- name: Upload Windows build artifacts - name: Upload Windows build artifacts
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4 uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # pin@v4
with: with:
+2 -23
View File
@@ -108,29 +108,8 @@ jobs:
cd ui/desktop cd ui/desktop
npm version "${VERSION}" --no-git-tag-version --allow-same-version npm version "${VERSION}" --no-git-tag-version --allow-same-version
- name: Cache Cargo registry - name: Cache Rust dependencies
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: Swatinem/rust-cache@v2
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-
- name: Cache Cargo index
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3
with:
path: ~/.cargo/index
key: ${{ runner.os }}-cargo-index
restore-keys: |
${{ runner.os }}-cargo-index
- name: Cache Cargo build
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3
with:
path: target
key: ${{ runner.os }}-cargo-build-release-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-build-release-
# Build the project # Build the project
- name: Build goosed - name: Build goosed
+41 -24
View File
@@ -1,3 +1,5 @@
name: CI
on: on:
push: push:
branches: branches:
@@ -10,8 +12,6 @@ on:
- main - main
workflow_dispatch: workflow_dispatch:
name: CI
jobs: jobs:
changes: changes:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -41,23 +41,21 @@ jobs:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Run cargo fmt - name: Run cargo fmt
run: source ./bin/activate-hermit && cargo fmt --check run: cargo fmt --check
rust-build-and-test: rust-build-and-test:
name: Build and Test Rust Project name: Build and Test Rust Project
runs-on: goose runs-on: ubuntu-latest
needs: changes needs: changes
if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request' if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request'
steps: steps:
- name: Checkout Code - name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4
- name: Activate hermit and set CARGO_HOME - uses: actions-rust-lang/setup-rust-toolchain@v1
run: |
source bin/activate-hermit
echo "CARGO_HOME=$CARGO_HOME" >> $GITHUB_ENV
echo "RUSTUP_HOME=$RUSTUP_HOME" >> $GITHUB_ENV
- name: Install Dependencies - name: Install Dependencies
run: | run: |
@@ -65,32 +63,52 @@ jobs:
sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev
- name: Cache Cargo artifacts - name: Cache Cargo artifacts
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: Swatinem/rust-cache@v2
with:
path: |
${{ env.CARGO_HOME }}/bin/
${{ env.CARGO_HOME }}/registry/index/
${{ env.CARGO_HOME }}/registry/cache/
${{ env.CARGO_HOME }}/git/db/
target/
key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-debug-
- name: Build and Test - name: Build and Test
run: | run: |
gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar' gnome-keyring-daemon --components=secrets --daemonize --unlock <<< 'foobar'
source ../bin/activate-hermit
export CARGO_INCREMENTAL=0 export CARGO_INCREMENTAL=0
cargo test --jobs 2 cargo test -- --skip scenario_tests::scenarios::tests
cargo test --jobs 1 scenario_tests::scenarios::tests
working-directory: crates working-directory: crates
rust-lint:
name: Lint Rust Code
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request'
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- uses: Swatinem/rust-cache@v2
- name: Lint - name: Lint
run: | run: |
source ./bin/activate-hermit source ./bin/activate-hermit
# use the non-hermit rust toolchain because the rust-cache action does not
# play nicely with hermit-managed rust
hermit uninstall rustup
export CARGO_INCREMENTAL=0 export CARGO_INCREMENTAL=0
./scripts/clippy-lint.sh ./scripts/clippy-lint.sh
openapi-schema-check:
name: Check OpenAPI Schema is Up-to-Date
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.code == 'true' || github.event_name != 'pull_request'
steps:
- name: Checkout Code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # pin@v4
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Cache Cargo artifacts
uses: Swatinem/rust-cache@v2
- name: Install Node.js Dependencies for OpenAPI Check - name: Install Node.js Dependencies for OpenAPI Check
run: source ../../bin/activate-hermit && npm ci run: source ../../bin/activate-hermit && npm ci
working-directory: ui/desktop working-directory: ui/desktop
@@ -98,6 +116,7 @@ jobs:
- name: Check OpenAPI Schema is Up-to-Date - name: Check OpenAPI Schema is Up-to-Date
run: | run: |
source ./bin/activate-hermit source ./bin/activate-hermit
hermit uninstall rustup
just check-openapi-schema just check-openapi-schema
desktop-lint: desktop-lint:
@@ -130,5 +149,3 @@ jobs:
- name: Run Tests - name: Run Tests
run: source ../../bin/activate-hermit && npm run test:run run: source ../../bin/activate-hermit && npm run test:run
working-directory: ui/desktop working-directory: ui/desktop
+3 -18
View File
@@ -55,33 +55,18 @@ jobs:
with: with:
ref: ${{ github.event.inputs.branch || github.ref }} ref: ${{ github.event.inputs.branch || github.ref }}
- name: Activate hermit and set CARGO_HOME - uses: actions-rust-lang/setup-rust-toolchain@v1
run: |
source bin/activate-hermit
echo "CARGO_HOME=$CARGO_HOME" >> $GITHUB_ENV
echo "RUSTUP_HOME=$RUSTUP_HOME" >> $GITHUB_ENV
- name: Install Dependencies - name: Install Dependencies
run: | run: |
sudo apt update -y sudo apt update -y
sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev
- name: Cache Cargo artifacts - name: Cache Rust dependencies
uses: actions/cache@2f8e54208210a422b2efd51efaa6bd6d7ca8920f # pin@v3 uses: Swatinem/rust-cache@v2
with:
path: |
${{ env.CARGO_HOME }}/bin/
${{ env.CARGO_HOME }}/registry/index/
${{ env.CARGO_HOME }}/registry/cache/
${{ env.CARGO_HOME }}/git/db/
target/
key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-release-
- name: Build Release Binary for Smoke Tests - name: Build Release Binary for Smoke Tests
run: | run: |
source ./bin/activate-hermit
cargo build --release cargo build --release
- name: Upload Binary for Smoke Tests - name: Upload Binary for Smoke Tests
+30 -30
View File
@@ -1,11 +1,11 @@
#!/bin/bash #!/bin/bash
# Baseline clippy rules - only fail on NEW violations # Baseline clippy rules - only fail on NEW violations
# #
# Format: "rule_name|violation_parser" # Format: "rule_name|violation_parser"
# #
# Violation parsers (run clippy on your rule to see which fits): # Violation parsers (run clippy on your rule to see which fits):
# function_name - When spans show: "fn my_function(..." # function_name - When spans show: "fn my_function(..."
# type_name - When spans show: "struct MyStruct" or "enum MyEnum" # type_name - When spans show: "struct MyStruct" or "enum MyEnum"
# file_only - When spans show file-level issues # file_only - When spans show file-level issues
# #
@@ -23,18 +23,18 @@ BASELINE_RULES=(
parse_violation() { parse_violation() {
local rule_code="$1" local rule_code="$1"
local violation_parser="$2" local violation_parser="$2"
case "$violation_parser" in case "$violation_parser" in
"function_name") "function_name")
jq -r 'select(.message.code.code == "'"$rule_code"'") | jq -r 'select(.message.code.code == "'"$rule_code"'") |
"\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split("fn ")[1] | split("(")[0])"' "\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split("fn ")[1] | split("(")[0])"'
;; ;;
"type_name") "type_name")
jq -r 'select(.message.code.code == "'"$rule_code"'") | jq -r 'select(.message.code.code == "'"$rule_code"'") |
"\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split(" ")[1] | split(" ")[0])"' "\(.message.spans[0].file_name)::\(.message.spans[0].text[0].text | split(" ")[1] | split(" ")[0])"'
;; ;;
"file_only") "file_only")
jq -r 'select(.message.code.code == "'"$rule_code"'") | jq -r 'select(.message.code.code == "'"$rule_code"'") |
"\(.message.spans[0].file_name)"' "\(.message.spans[0].file_name)"'
;; ;;
*) *)
@@ -53,22 +53,22 @@ get_baseline_file() {
generate_baseline() { generate_baseline() {
local rule_name="$1" local rule_name="$1"
[[ -z "$rule_name" ]] && { echo "Missing rule name"; return 1; } [[ -z "$rule_name" ]] && { echo "Missing rule name"; return 1; }
local violation_parser="" local violation_parser=""
for rule in "${BASELINE_RULES[@]}"; do for rule in "${BASELINE_RULES[@]}"; do
[[ "${rule%|*}" == "$rule_name" ]] && { violation_parser="${rule#*|}"; break; } [[ "${rule%|*}" == "$rule_name" ]] && { violation_parser="${rule#*|}"; break; }
done done
[[ -z "$violation_parser" ]] && { echo "Unknown rule: $rule_name"; return 1; } [[ -z "$violation_parser" ]] && { echo "Unknown rule: $rule_name"; return 1; }
local baseline_file=$(get_baseline_file "$rule_name") local baseline_file=$(get_baseline_file "$rule_name")
cargo clippy --jobs 2 --message-format=json -- -W "$rule_name" | \ cargo clippy --jobs 2 --message-format=json -- -W "$rule_name" | \
parse_violation "$rule_name" "$violation_parser" | \ parse_violation "$rule_name" "$violation_parser" | \
sort > "$baseline_file" sort > "$baseline_file"
echo "✅ Generated baseline for $rule_name ($(wc -l < "$baseline_file") violations)" echo "✅ Generated baseline for $rule_name ($(wc -l < "$baseline_file") violations)"
} }
@@ -79,23 +79,23 @@ check_rule_from_json() {
local rule_name="$2" local rule_name="$2"
local violation_parser="$3" local violation_parser="$3"
local baseline_file="$4" local baseline_file="$4"
echo " → Checking $rule_name" echo " → Checking $rule_name"
if [[ ! -f "$baseline_file" ]]; then if [[ ! -f "$baseline_file" ]]; then
echo "$rule_name: baseline file not found" echo "$rule_name: baseline file not found"
return 1 return 1
fi fi
local temp_parsed=$(mktemp) local temp_parsed=$(mktemp)
cat "$temp_json" | parse_violation "$rule_name" "$violation_parser" | sort > "$temp_parsed" cat "$temp_json" | parse_violation "$rule_name" "$violation_parser" | sort > "$temp_parsed"
local new_violations_file=$(mktemp) local new_violations_file=$(mktemp)
diff <(sort "$baseline_file") <(sort "$temp_parsed") | grep "^>" | cut -c3- > "$new_violations_file" diff <(sort "$baseline_file") <(sort "$temp_parsed") | grep "^>" | cut -c3- > "$new_violations_file"
if [[ -s "$new_violations_file" ]]; then if [[ -s "$new_violations_file" ]]; then
echo "$rule_name: NEW violations found:" echo "$rule_name: NEW violations found:"
while IFS= read -r violation; do while IFS= read -r violation; do
# Extract all violations for this rule and find the matching one # Extract all violations for this rule and find the matching one
cat "$temp_json" | jq -c 'select(.message.code.code == "'"$rule_name"'")' 2>/dev/null | while read -r json_line; do cat "$temp_json" | jq -c 'select(.message.code.code == "'"$rule_name"'")' 2>/dev/null | while read -r json_line; do
@@ -105,13 +105,13 @@ check_rule_from_json() {
fi fi
done done
done < "$new_violations_file" done < "$new_violations_file"
rm "$temp_parsed" "$new_violations_file" rm "$temp_parsed" "$new_violations_file"
return 1 return 1
fi fi
rm "$new_violations_file" rm "$new_violations_file"
echo "$rule_name: ok" echo "$rule_name: ok"
rm "$temp_parsed" rm "$temp_parsed"
return 0 return 0
@@ -119,31 +119,31 @@ check_rule_from_json() {
check_all_baseline_rules() { check_all_baseline_rules() {
echo "🔍 Checking baseline clippy rules..." echo "🔍 Checking baseline clippy rules..."
local clippy_flags="" local clippy_flags=""
for rule in "${BASELINE_RULES[@]}"; do for rule in "${BASELINE_RULES[@]}"; do
local rule_name="${rule%|*}" local rule_name="${rule%|*}"
clippy_flags="$clippy_flags -W $rule_name" clippy_flags="$clippy_flags -W $rule_name"
done done
local temp_json=$(mktemp) local temp_json=$(mktemp)
cargo clippy --jobs 2 --message-format=json -- $clippy_flags > "$temp_json" cargo clippy --jobs 2 --message-format=json -- $clippy_flags | tee "$temp_json"
local failed_rules=() local failed_rules=()
# Check each rule against its baseline # Check each rule against its baseline
for rule in "${BASELINE_RULES[@]}"; do for rule in "${BASELINE_RULES[@]}"; do
local rule_name="${rule%|*}" local rule_name="${rule%|*}"
local violation_parser="${rule#*|}" local violation_parser="${rule#*|}"
local baseline_file=$(get_baseline_file "$rule_name") local baseline_file=$(get_baseline_file "$rule_name")
if ! check_rule_from_json "$temp_json" "$rule_name" "$violation_parser" "$baseline_file"; then if ! check_rule_from_json "$temp_json" "$rule_name" "$violation_parser" "$baseline_file"; then
failed_rules+=("$rule_name") failed_rules+=("$rule_name")
fi fi
done done
rm "$temp_json" rm "$temp_json"
if [[ ${#failed_rules[@]} -gt 0 ]]; then if [[ ${#failed_rules[@]} -gt 0 ]]; then
echo "" echo ""
echo "❌ Failed baseline checks for: ${failed_rules[*]}" echo "❌ Failed baseline checks for: ${failed_rules[*]}"
@@ -156,4 +156,4 @@ check_all_baseline_rules() {
if [[ "$1" == "generate" ]]; then if [[ "$1" == "generate" ]]; then
generate_baseline "$2" generate_baseline "$2"
fi fi