Skip to content

Commit bff1f07

Browse files
authored
feat: implement GitHub action for soteria (#2)
* feat: read safe address from file * cleanup: log struct * feat: add a dash of colour, migrate to clap * feat: make reporting better * feat: implement dockerfile * feat: build CLI statically * feat: add workflow * fmt: cargo fmt * feat: bump upload-artifact action * feat: update release to make more images, add action.yml file * feat: add job to upload artifacts * feat: update action name * feat: bump checkout action * feat: bump version to align with github version
1 parent e597fb8 commit bff1f07

File tree

5 files changed

+306
-14
lines changed

5 files changed

+306
-14
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
build:
1313
runs-on: ubuntu-latest
1414
steps:
15-
- uses: actions/checkout@v4
15+
- uses: actions/checkout@v6
1616

1717
- uses: dtolnay/rust-toolchain@stable
1818
with:

.github/workflows/release.yml

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,116 @@ on:
77

88
env:
99
IMAGE_NAME: monadfoundation/soteria
10+
CARGO_TERM_COLOR: always
1011

1112
jobs:
12-
artifacts:
13-
runs-on: ubuntu-latest
13+
binaries:
14+
name: Build ${{ matrix.platform.name }}
15+
runs-on: ${{ matrix.platform.runner }}
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
platform:
20+
- name: linux x86_64
21+
runner: ubuntu-latest
22+
target: x86_64-unknown-linux-gnu
23+
artifact: soteria-linux-x86_64
24+
25+
- name: linux arm64
26+
runner: ubuntu-24.04-arm
27+
target: aarch64-unknown-linux-gnu
28+
artifact: soteria-linux-arm64
29+
30+
# macOS Intel
31+
- name: macos x86_64
32+
runner: macos-15-intel
33+
target: x86_64-apple-darwin
34+
artifact: soteria-darwin-x86_64
35+
36+
# macOS Apple Silicon
37+
- name: macos arm64
38+
runner: macos-26
39+
target: aarch64-apple-darwin
40+
artifact: soteria-darwin-arm64
41+
42+
# Windows x86_64
43+
- name: windows x86_64
44+
runner: windows-latest
45+
target: x86_64-pc-windows-msvc
46+
artifact: soteria-windows-x86_64
47+
48+
# Windows ARM64
49+
- name: windows arm64
50+
runner: windows-11-arm
51+
target: aarch64-pc-windows-msvc
52+
artifact: soteria-windows-arm64
53+
1454
steps:
15-
- uses: actions/checkout@v5
55+
- name: Checkout
56+
uses: actions/checkout@v6
1657

17-
- uses: dtolnay/rust-toolchain@stable
58+
- name: Install Rust toolchain
59+
uses: dtolnay/rust-toolchain@stable
1860
with:
1961
toolchain: stable
62+
targets: ${{ matrix.platform.target }}
2063
components: rustfmt
2164

22-
- uses: Swatinem/rust-cache@v2
65+
- name: Cache dependencies
66+
uses: Swatinem/rust-cache@v2
2367
with:
68+
key: ${{ matrix.platform.target }}
2469
cache-on-failure: true
2570

26-
- run: cargo build --release --locked --all-features -v
27-
28-
- name: Upload release version artifact
29-
uses: actions/upload-artifact@v4
71+
- name: Build release binary
72+
run: cargo build --release --locked --all-features --target ${{ matrix.platform.target }} -v
73+
74+
- name: Prepare artifact (Unix)
75+
if: runner.os != 'Windows'
76+
run: |
77+
mkdir -p artifacts
78+
cp target/${{ matrix.platform.target }}/release/soteria artifacts/
79+
cd artifacts
80+
tar -czvf ${{ matrix.platform.artifact }}.tar.gz soteria
81+
rm soteria
82+
83+
- name: Prepare artifact (Windows)
84+
if: runner.os == 'Windows'
85+
shell: pwsh
86+
run: |
87+
New-Item -ItemType Directory -Force -Path artifacts
88+
Copy-Item "target/${{ matrix.platform.target }}/release/soteria.exe" -Destination "artifacts/"
89+
Compress-Archive -Path "artifacts/soteria.exe" -DestinationPath "artifacts/${{ matrix.platform.artifact }}.zip"
90+
Remove-Item "artifacts/soteria.exe"
91+
92+
- name: Upload artifact
93+
uses: actions/upload-artifact@v5
94+
with:
95+
name: ${{ matrix.platform.artifact }}
96+
path: artifacts/*
97+
if-no-files-found: error
98+
99+
publish:
100+
name: Publish GitHub Release assets
101+
runs-on: ubuntu-latest
102+
needs: [binaries]
103+
permissions:
104+
contents: write
105+
steps:
106+
- name: Download build artifacts
107+
uses: actions/download-artifact@v5
108+
with:
109+
path: dist
110+
merge-multiple: true
111+
112+
- name: Update release and upload assets
113+
uses: softprops/action-gh-release@v2
30114
with:
31-
name: soteria
32-
path: ./target/release/soteria
115+
generate_release_notes: true
116+
fail_on_unmatched_files: true
117+
files: |
118+
dist/*.tar.gz
119+
dist/*.zip
33120
34121
docker:
35122
runs-on: ubuntu-latest
@@ -53,6 +140,10 @@ jobs:
53140
uses: docker/build-push-action@v6
54141
with:
55142
push: true
143+
platforms: linux/amd64,linux/arm64
56144
sbom: true
57145
provenance: mode=max
58146
tags: ${{ steps.meta.outputs.tags }}
147+
labels: ${{ steps.meta.outputs.labels }}
148+
cache-from: type=gha
149+
cache-to: type=gha,mode=max

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "soteria"
33
authors = ["QEDK <qedk@monad.foundation>"]
44
license = "Apache-2.0"
5-
version = "0.1.0"
5+
version = "0.1.6"
66
edition = "2024"
77

88
[dependencies]

action.yml

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
name: 'run soteria CLI'
2+
description: 'uses the soteria CLI to validate safe transaction hashes in JSON log files'
3+
author: 'Monad Foundation'
4+
5+
branding:
6+
icon: 'shield'
7+
color: 'purple'
8+
9+
inputs:
10+
directory:
11+
description: 'Path to the directory containing JSON files to validate'
12+
required: true
13+
version:
14+
description: 'Version of Soteria to use (e.g., "v0.1.5" or "latest")'
15+
required: false
16+
default: 'latest'
17+
github-token:
18+
description: 'GitHub token for API requests (to avoid rate limiting)'
19+
required: false
20+
default: ${{ github.token }}
21+
fail-on-error:
22+
description: 'Whether to fail the workflow if validation errors are found'
23+
required: false
24+
default: 'true'
25+
26+
outputs:
27+
validation-result:
28+
description: 'The result of the validation (success or failure)'
29+
value: ${{ steps.run-soteria.outputs.result }}
30+
soteria-version:
31+
description: 'The version of Soteria that was used'
32+
value: ${{ steps.download.outputs.tag_name }}
33+
34+
runs:
35+
using: 'composite'
36+
steps:
37+
- name: Determine platform
38+
id: platform
39+
shell: bash
40+
run: |
41+
OS="${{ runner.os }}"
42+
ARCH="${{ runner.arch }}"
43+
44+
case "$OS" in
45+
Linux)
46+
case "$ARCH" in
47+
X64)
48+
echo "target=x86_64-unknown-linux-gnu" >> $GITHUB_OUTPUT
49+
echo "asset_pattern=soteria-*linux*x86_64*" >> $GITHUB_OUTPUT
50+
echo "fallback_pattern=soteria*linux*" >> $GITHUB_OUTPUT
51+
;;
52+
ARM64)
53+
echo "target=aarch64-unknown-linux-gnu" >> $GITHUB_OUTPUT
54+
echo "asset_pattern=soteria-*linux*aarch64*" >> $GITHUB_OUTPUT
55+
echo "fallback_pattern=soteria*linux*arm*" >> $GITHUB_OUTPUT
56+
;;
57+
*)
58+
echo "::error::Unsupported architecture: $ARCH"
59+
exit 1
60+
;;
61+
esac
62+
;;
63+
macOS)
64+
case "$ARCH" in
65+
X64)
66+
echo "target=x86_64-apple-darwin" >> $GITHUB_OUTPUT
67+
echo "asset_pattern=soteria-*darwin*x86_64*" >> $GITHUB_OUTPUT
68+
echo "fallback_pattern=soteria*darwin*" >> $GITHUB_OUTPUT
69+
;;
70+
ARM64)
71+
echo "target=aarch64-apple-darwin" >> $GITHUB_OUTPUT
72+
echo "asset_pattern=soteria-*darwin*aarch64*" >> $GITHUB_OUTPUT
73+
echo "fallback_pattern=soteria*darwin*arm*" >> $GITHUB_OUTPUT
74+
;;
75+
*)
76+
echo "::error::Unsupported architecture: $ARCH"
77+
exit 1
78+
;;
79+
esac
80+
;;
81+
Windows)
82+
echo "target=x86_64-pc-windows-msvc" >> $GITHUB_OUTPUT
83+
echo "asset_pattern=soteria-*windows*x86_64*" >> $GITHUB_OUTPUT
84+
echo "fallback_pattern=soteria*windows*" >> $GITHUB_OUTPUT
85+
;;
86+
*)
87+
echo "::error::Unsupported operating system: $OS"
88+
exit 1
89+
;;
90+
esac
91+
92+
echo "os=$OS" >> $GITHUB_OUTPUT
93+
echo "arch=$ARCH" >> $GITHUB_OUTPUT
94+
95+
- name: Download Soteria binary
96+
id: download
97+
uses: robinraju/release-downloader@v1
98+
with:
99+
repository: 'monad-developers/soteria'
100+
latest: ${{ inputs.version == 'latest' }}
101+
tag: ${{ inputs.version != 'latest' && inputs.version || '' }}
102+
fileName: '*'
103+
out-file-path: '${{ runner.temp }}/soteria-download'
104+
extract: true
105+
token: ${{ inputs.github-token }}
106+
107+
- name: Find and setup Soteria binary
108+
id: setup
109+
shell: bash
110+
run: |
111+
DOWNLOAD_DIR="${{ runner.temp }}/soteria-download"
112+
INSTALL_DIR="${{ runner.temp }}/soteria-bin"
113+
mkdir -p "$INSTALL_DIR"
114+
115+
echo "Looking for Soteria binary in: $DOWNLOAD_DIR"
116+
ls -la "$DOWNLOAD_DIR" || true
117+
118+
# Look for the binary - try various patterns
119+
BINARY=""
120+
121+
# First, try to find a binary matching the platform
122+
for pattern in "soteria" "soteria-${{ steps.platform.outputs.target }}" "soteria_${{ steps.platform.outputs.target }}"; do
123+
if [ -f "$DOWNLOAD_DIR/$pattern" ]; then
124+
BINARY="$DOWNLOAD_DIR/$pattern"
125+
break
126+
fi
127+
if [ -f "$DOWNLOAD_DIR/${pattern}.exe" ]; then
128+
BINARY="$DOWNLOAD_DIR/${pattern}.exe"
129+
break
130+
fi
131+
done
132+
133+
# If not found, search recursively for any soteria binary
134+
if [ -z "$BINARY" ]; then
135+
BINARY=$(find "$DOWNLOAD_DIR" -type f \( -name "soteria" -o -name "soteria.exe" -o -name "soteria-*" \) 2>/dev/null | head -n 1)
136+
fi
137+
138+
if [ -z "$BINARY" ] || [ ! -f "$BINARY" ]; then
139+
echo "::warning::No pre-built binary found. Building from source..."
140+
141+
# Install Rust if needed
142+
if ! command -v cargo &> /dev/null; then
143+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
144+
source "$HOME/.cargo/env"
145+
fi
146+
147+
# Install soteria from source
148+
cargo install --git https://github.com/monad-developers/soteria.git --root "$INSTALL_DIR"
149+
BINARY="$INSTALL_DIR/bin/soteria"
150+
else
151+
cp "$BINARY" "$INSTALL_DIR/soteria"
152+
BINARY="$INSTALL_DIR/soteria"
153+
fi
154+
155+
# Make executable (on Unix systems)
156+
if [ "${{ runner.os }}" != "Windows" ]; then
157+
chmod +x "$BINARY"
158+
fi
159+
160+
echo "binary_path=$BINARY" >> $GITHUB_OUTPUT
161+
echo "Binary location: $BINARY"
162+
163+
# Verify binary
164+
"$BINARY" --help || "$BINARY" -h || echo "Binary verification skipped"
165+
166+
- name: Run Soteria validation
167+
id: run-soteria
168+
shell: bash
169+
run: |
170+
BINARY="${{ steps.setup.outputs.binary_path }}"
171+
DIRECTORY="${{ inputs.directory }}"
172+
173+
echo "Running Soteria on directory: $DIRECTORY"
174+
echo "Using binary: $BINARY"
175+
176+
# Validate directory exists
177+
if [ ! -d "$DIRECTORY" ]; then
178+
echo "::error::Directory does not exist: $DIRECTORY"
179+
exit 1
180+
fi
181+
182+
# Run soteria
183+
set +e
184+
OUTPUT=$("$BINARY" "$DIRECTORY" 2>&1)
185+
EXIT_CODE=$?
186+
set -e
187+
188+
echo "$OUTPUT"
189+
190+
if [ $EXIT_CODE -eq 0 ]; then
191+
echo "result=success" >> $GITHUB_OUTPUT
192+
echo "::notice::Soteria validation completed successfully"
193+
else
194+
echo "result=failure" >> $GITHUB_OUTPUT
195+
if [ "${{ inputs.fail-on-error }}" == "true" ]; then
196+
echo "::error::Soteria validation failed"
197+
exit $EXIT_CODE
198+
else
199+
echo "::warning::Soteria validation found issues (exit code: $EXIT_CODE)"
200+
fi
201+
fi

0 commit comments

Comments
 (0)