1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
name: Release
# Triggered only by pushing a tag like v1.0.0, v1.2.3, etc.
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
# ── 1. Quality checks (same as the CI workflow) ────────────────────────────
ci:
name: CI checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ci-cargo-${{ hashFiles('**/Cargo.lock') }}
- run: cargo test --verbose
- run: cargo clippy -- -D warnings
- run: cargo fmt --check
# ── 2. Build release binaries ──────────────────────────────────────────────
#
# The four platforms are built in parallel and independently.
# Each job uploads its archive as a GitHub Actions artifact,
# which the final "publish" job then attaches to the Release.
#
# runner → target mapping:
# ubuntu-22.04 → x86_64-unknown-linux-gnu (older glibc for wider compat)
# macos-latest → x86_64-apple-darwin (ARM runner, cross-compiled)
# macos-latest → aarch64-apple-darwin (Apple Silicon runner, native)
# windows-latest → x86_64-pc-windows-msvc (native)
build:
name: Build · ${{ matrix.target }}
needs: ci
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
# Built on Ubuntu 22.04 (glibc 2.35) so the binary also runs on
# 22.04 hosts — ubuntu-latest moved to 24.04 (glibc 2.39).
- target: x86_64-unknown-linux-gnu
runner: ubuntu-22.04
binary: omny
archive: omny-x86_64-unknown-linux-gnu.tar.gz
- target: x86_64-apple-darwin
runner: macos-latest
binary: omny
archive: omny-x86_64-apple-darwin.tar.gz
- target: aarch64-apple-darwin
runner: macos-latest
binary: omny
archive: omny-aarch64-apple-darwin.tar.gz
- target: x86_64-pc-windows-msvc
runner: windows-latest
binary: omny.exe
archive: omny-x86_64-pc-windows-msvc.zip
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ matrix.target }}-cargo-
# Build the release binary (optimized, stripped)
- name: Build release binary
run: cargo build --release --locked --target ${{ matrix.target }}
# Package for Unix (tar.gz)
- name: Package (Unix)
if: runner.os != 'Windows'
run: |
cd target/${{ matrix.target }}/release
tar czf "${{ matrix.archive }}" ${{ matrix.binary }}
mv "${{ matrix.archive }}" "${{ github.workspace }}/"
# Package for Windows (zip)
- name: Package (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
cd target/${{ matrix.target }}/release
Compress-Archive -Path ${{ matrix.binary }} -DestinationPath "${{ github.workspace }}/${{ matrix.archive }}"
# Upload the archive as an artifact — the publish job downloads it
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.archive }}
path: ${{ matrix.archive }}
retention-days: 1
if-no-files-found: error
# ── 3. Create the GitHub Release and attach the binaries ───────────────────
publish:
name: Publish GitHub Release
needs: build
runs-on: ubuntu-latest
permissions:
contents: write # required to create the Release
steps:
- uses: actions/checkout@v4
# Download all four archives from the previous jobs
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
# Make sure all files are present
- name: List artifacts
run: ls -lh artifacts/
# Generate SHA256SUMS with bare filenames so the in-app updater can
# verify a downloaded archive against its checksum.
- name: Generate checksums
run: |
cd artifacts
sha256sum omny-* > SHA256SUMS
cat SHA256SUMS
# Extract the current release block from CHANGELOG.md: from the
# "## X.Y.Z" heading down to the next "## " heading or "---" rule.
- name: Extract changelog entry
id: changelog
run: |
VERSION="${GITHUB_REF_NAME#v}" # strip the leading "v" from the tag
BODY=$(awk "/^## ${VERSION} /{found=1; next} found && (/^## /||/^---\$/){exit} found{print}" CHANGELOG.md)
# Pass the multi-line text through GITHUB_OUTPUT
{
echo 'body<<CHANGELOG_EOF'
echo "$BODY"
echo 'CHANGELOG_EOF'
} >> "$GITHUB_OUTPUT"
# Create the Release and attach all binaries in one step
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: OmnySSH ${{ github.ref_name }}
body: ${{ steps.changelog.outputs.body }}
draft: false
prerelease: false
fail_on_unmatched_files: true
files: |
artifacts/omny-x86_64-unknown-linux-gnu.tar.gz
artifacts/omny-x86_64-apple-darwin.tar.gz
artifacts/omny-aarch64-apple-darwin.tar.gz
artifacts/omny-x86_64-pc-windows-msvc.zip
artifacts/SHA256SUMS