OXYGENHUB
# 2b95bc24d7d6 oxygen / vendor / crc-fast / .kiro / specs / github-release-automation / design.md
15.5 KiB · Markdown · last changed Strata: the cloud stores send through ureq, so every release target links 1 month ago renderedsource blame history raw
1
# Design Document
2
3
## Overview
4
5
This design implements a GitHub Actions workflow that automatically builds and publishes binary packages when version tags are pushed to the repository. The workflow leverages the existing test infrastructure, builds optimized binaries for five target platforms, packages them according to platform conventions, and uploads them as GitHub release assets.
6
7
The solution uses a single workflow file that orchestrates testing, building, packaging, and publishing steps. It reuses the existing test workflow to ensure quality gates are met before creating releases.
8
9
## Architecture
10
11
### Workflow Structure
12
13
The release workflow consists of three main stages:
14
15
1. **Validation Stage**: Triggers existing test workflow and waits for completion
16
2. **Build Stage**: Compiles release binaries for all target platforms in parallel
17
3. **Publish Stage**: Creates packages, generates checksums, and uploads to GitHub release
18
19
### Workflow Trigger
20
21
```yaml
22
on:
23
  push:
24
    tags:
25
      - '[0-9]+.[0-9]+.[0-9]+'
26
```
27
28
This pattern matches semantic version tags like `1.5.0`, `2.0.1`, etc.
29
30
### Build Matrix
31
32
The workflow uses a matrix strategy to build for multiple platforms:
33
34
| Target Triple | OS Runner | Package Extension | Runner Rationale |
35
|--------------|-----------|-------------------|------------------|
36
| x86_64-unknown-linux-gnu | ubuntu-22.04 | .tar.gz | Native x86_64 Linux runner, explicit version for stability |
37
| aarch64-unknown-linux-gnu | ubuntu-22.04-arm | .tar.gz | Native ARM64 Linux runner, explicit version for stability |
38
| aarch64-apple-darwin | macos-14 | .tar.gz | Native Apple Silicon runner (M1/M2), explicit version for stability |
39
| x86_64-pc-windows-msvc | windows-2022 | .zip | Native x86_64 Windows runner, explicit version for stability |
40
| aarch64-pc-windows-msvc | windows-11-arm | .zip | Native ARM64 Windows runner (only ARM64 option available) |
41
42
**Runner Selection Rationale**:
43
44
#### General Principles
45
1. **Native Compilation**: Each runner matches the target architecture for optimal performance and to leverage architecture-specific CPU features (AVX-512, NEON, etc.)
46
2. **Binary Compatibility**: Binaries built on older OS versions are forward-compatible with newer versions, but not backward-compatible
47
3. **Single Binary Per Architecture**: One binary package per architecture is sufficient due to OS forward compatibility
48
4. **Explicit Versions**: Using explicit runner versions (ubuntu-22.04, windows-2022, macos-14) instead of -latest provides stability and predictability, preventing unexpected changes when GitHub updates their -latest pointers
49
50
#### Platform-Specific Decisions
51
52
**Linux (ubuntu-22.04 for x86_64, ubuntu-22.04-arm for aarch64)**:
53
- Explicit version (22.04) ensures consistent build environment over time
54
- Ubuntu 22.04 uses glibc 2.35, providing good compatibility with modern distributions
55
- Ubuntu binaries have excellent forward compatibility across distributions (Ubuntu, Debian, RHEL, etc.)
56
- When ubuntu-latest moves to 24.04 or newer, our release builds remain stable on 22.04
57
- No need for multiple Linux versions; one binary per architecture covers the ecosystem
58
- Using explicit versions allows intentional upgrades rather than automatic changes
59
60
**macOS (macos-14 for aarch64)**:
61
- `macos-14` is the first stable Apple Silicon (M1/M2) runner
62
- macOS binaries built on older versions run on newer versions (forward compatible)
63
- `macos-15` and `macos-latest` would work but offer no compatibility advantage
64
- Using `macos-14` provides maximum compatibility (works on macOS 14, 15, and future versions)
65
- No x86_64 macOS build needed: Apple Silicon Macs can run x86_64 binaries via Rosetta 2, but native ARM64 is preferred
66
- Single ARM64 binary covers all Apple Silicon Macs (M1, M2, M3, M4, etc.)
67
68
**Windows (windows-2022 for x86_64, windows-11-arm for aarch64)**:
69
- Explicit version (2022) ensures consistent build environment over time
70
- Windows Server 2022 binaries have excellent forward compatibility (run on Windows 11, future versions)
71
- MSVC runtime is statically linked in Rust release builds, eliminating runtime dependencies
72
- When windows-latest moves to Server 2025 or newer, our release builds remain stable on 2022
73
- `windows-11-arm` is the only ARM64 Windows runner available (no version choice)
74
- Using explicit versions allows intentional upgrades rather than automatic changes
75
- No need for multiple Windows versions; one binary per architecture covers the ecosystem
76
77
#### Why Not Multiple OS Versions?
78
79
**Rejected Approach**: Building separate packages for each OS version (e.g., macos-14, macos-15, ubuntu-22.04, ubuntu-24.04)
80
81
**Reasons**:
82
1. **Forward Compatibility**: Binaries built on older OS versions work on newer versions
83
2. **Maintenance Burden**: Multiple packages per architecture increases complexity without benefit
84
3. **User Confusion**: Users would need to choose between multiple packages for the same architecture
85
4. **Storage Costs**: More packages means more storage and bandwidth
86
5. **Testing Overhead**: The existing test workflow already validates across multiple OS versions (macos-14, macos-15, ubuntu-22.04, ubuntu-24.04, etc.), proving binary compatibility
87
88
**Conclusion**: One binary package per architecture provides maximum compatibility with minimum complexity. The test workflow validates compatibility across OS versions, while the release workflow builds on the oldest supported version for maximum forward compatibility.
89
90
## Components and Interfaces
91
92
### 1. Release Workflow File
93
94
**Location**: `.github/workflows/release.yml`
95
96
**Responsibilities**:
97
- Trigger on version tags
98
- Wait for test workflow completion
99
- Build release binaries for all targets
100
- Create platform-specific packages
101
- Generate SHA256 checksums
102
- Upload packages and checksums to GitHub release
103
104
**Key Jobs**:
105
106
#### Job: `validate`
107
- Waits for the existing test workflow to complete for the tagged commit
108
- Uses an action like `lewagon/wait-on-check-action` to poll test workflow status
109
- Fails the release if tests don't pass
110
- Includes timeout to prevent infinite waiting (e.g., 60 minutes)
111
- Runs quality checks (fmt, clippy) after tests pass
112
113
#### Job: `build` (matrix)
114
- Depends on `validate` job
115
- Checks out code
116
- Sets up Rust toolchain (stable)
117
- Runs quality checks (fmt, clippy)
118
- Builds release binaries with `cargo build --release` (LTO and stripping handled by Cargo.toml profile)
119
- Builds CLI binaries (checksum, arch-check, get-custom-params)
120
- Stages files in platform-specific directory structure
121
- Creates compressed package
122
- Generates SHA256 checksum
123
- Uploads package and checksum as artifacts
124
125
#### Job: `publish`
126
- Depends on all `build` jobs
127
- Downloads all artifacts
128
- Checks if GitHub release already exists for the tag
129
- If release exists, uploads packages and checksums to existing release
130
- If release doesn't exist, creates new release and uploads assets
131
- Allows manual release creation with custom notes before workflow runs
132
133
### 2. Package Structure
134
135
#### Linux Packages (x86_64 and aarch64)
136
137
```
138
crc-fast-{version}-linux-{arch}/
139
├── lib/
140
│   ├── libcrc_fast.so
141
│   └── libcrc_fast.a
142
├── include/
143
│   └── libcrc_fast.h
144
├── bin/
145
│   ├── checksum
146
│   ├── arch-check
147
│   └── get-custom-params
148
├── LICENSE-MIT
149
├── LICENSE-Apache
150
├── VERSION
151
└── README.txt
152
```
153
154
#### macOS Package (aarch64)
155
156
```
157
crc-fast-{version}-macos-aarch64/
158
├── lib/
159
│   ├── libcrc_fast.dylib
160
│   └── libcrc_fast.a
161
├── include/
162
│   └── libcrc_fast.h
163
├── bin/
164
│   ├── checksum
165
│   ├── arch-check
166
│   └── get-custom-params
167
├── LICENSE-MIT
168
├── LICENSE-Apache
169
├── VERSION
170
└── README.txt
171
```
172
173
#### Windows Packages (x86_64 and aarch64)
174
175
```
176
crc-fast-{version}-windows-{arch}/
177
├── bin/
178
│   ├── crc_fast.dll
179
│   ├── checksum.exe
180
│   ├── arch-check.exe
181
│   └── get-custom-params.exe
182
├── lib/
183
│   ├── crc_fast.dll.lib    (import library for linking against DLL)
184
│   └── crc_fast.lib         (static library)
185
├── include/
186
│   └── libcrc_fast.h
187
├── LICENSE-MIT
188
├── LICENSE-Apache
189
├── VERSION
190
└── README.txt
191
```
192
193
**Windows Library Files Explained**:
194
- `crc_fast.dll`: The dynamic library containing the actual code
195
- `crc_fast.dll.lib`: Import library needed to link against the DLL at compile time
196
- `crc_fast.lib`: Static library for static linking (standalone, doesn't need DLL)
197
198
### 3. Package Metadata Files
199
200
#### VERSION File
201
Contains the version number extracted from the git tag:
202
```
203
1.5.0
204
```
205
206
#### README.txt File
207
Provides basic installation and usage instructions:
208
```
209
crc-fast Binary Distribution
210
Version: {version}
211
Platform: {platform}-{arch}
212
213
Contents:
214
- Library files (dynamic and static)
215
- Header file for C/C++ integration
216
- Command-line utilities
217
218
Installation:
219
[Platform-specific instructions]
220
221
Usage:
222
See https://github.com/awesomized/crc-fast-rust for documentation
223
224
License: MIT OR Apache-2.0
225
```
226
227
### 4. Checksum Files
228
229
Each package has an accompanying `.sha256` file:
230
```
231
{sha256_hash}  crc-fast-{version}-{platform}-{arch}.{ext}
232
```
233
234
## Data Models
235
236
### Build Artifact Structure
237
238
```yaml
239
artifacts:
240
  - name: "crc-fast-{version}-{platform}-{arch}.{ext}"
241
    type: "package"
242
    checksum: "{sha256_hash}"
243
  - name: "crc-fast-{version}-{platform}-{arch}.{ext}.sha256"
244
    type: "checksum"
245
```
246
247
### Matrix Configuration
248
249
```yaml
250
matrix:
251
  include:
252
    - target: x86_64-unknown-linux-gnu
253
      os: ubuntu-22.04
254
      platform: linux
255
      arch: x86_64
256
      ext: tar.gz
257
      
258
    - target: aarch64-unknown-linux-gnu
259
      os: ubuntu-22.04-arm
260
      platform: linux
261
      arch: aarch64
262
      ext: tar.gz
263
      
264
    - target: aarch64-apple-darwin
265
      os: macos-14
266
      platform: macos
267
      arch: aarch64
268
      ext: tar.gz
269
      
270
    - target: x86_64-pc-windows-msvc
271
      os: windows-2022
272
      platform: windows
273
      arch: x86_64
274
      ext: zip
275
      
276
    - target: aarch64-pc-windows-msvc
277
      os: windows-11-arm
278
      platform: windows
279
      arch: aarch64
280
      ext: zip
281
```
282
283
## Error Handling
284
285
### Test Failure
286
- If the test workflow fails, the `validate` job fails
287
- The `build` jobs don't execute (dependency chain)
288
- No release is created
289
- GitHub Actions shows clear failure status
290
291
### Build Failure
292
- If any platform build fails, that specific matrix job fails
293
- Other platform builds continue
294
- The `publish` job waits for all builds
295
- If any build failed, `publish` job is skipped
296
- Partial releases are prevented
297
298
### Quality Check Failure
299
- If `cargo fmt --check` fails, build stops
300
- If `cargo clippy` produces warnings, build stops
301
- Ensures all released binaries meet quality standards
302
303
### Missing Files
304
- Build script validates all expected files exist before packaging
305
- Fails with clear error message if files are missing
306
- Prevents incomplete packages
307
308
### Upload Failure
309
- If GitHub release creation fails, workflow fails
310
- If asset upload fails, workflow retries (GitHub Actions default)
311
- All artifacts remain available for manual inspection
312
313
## Testing Strategy
314
315
### Pre-Release Testing
316
1. The existing test workflow must pass completely
317
2. All platforms in the test matrix must succeed
318
3. Format and clippy checks must pass
319
320
### Build Verification
321
1. Verify all expected files are present in target/release
322
2. Check file sizes are reasonable (not empty)
323
3. Validate binary executables are actually executable
324
4. Confirm library files have correct extensions
325
326
### Package Verification
327
1. Verify package structure matches specification
328
2. Check all metadata files are included
329
3. Validate checksums are generated correctly
330
4. Ensure package names follow naming convention
331
332
### Integration Testing
333
1. Test workflow on a feature branch with test tags
334
2. Verify packages can be downloaded
335
3. Test that libraries can be linked
336
4. Verify CLI binaries execute correctly
337
5. Validate checksums match package contents
338
339
### Manual Testing Checklist
340
Before first production release:
341
- [ ] Create test tag on feature branch
342
- [ ] Verify workflow triggers correctly
343
- [ ] Download each platform package
344
- [ ] Extract and verify contents
345
- [ ] Test linking dynamic library
346
- [ ] Test linking static library
347
- [ ] Run each CLI binary
348
- [ ] Verify checksums
349
- [ ] Test on actual target platforms
350
351
## Design Decisions
352
353
### Decision 1: Single Package Per Platform
354
**Rationale**: Combining libraries and CLI tools in one package simplifies distribution and ensures users get everything they need. Separate packages would create confusion about which package to download.
355
356
**Alternative Considered**: Separate library and CLI packages. Rejected because it adds complexity for minimal benefit.
357
358
### Decision 2: Include Both Dynamic and Static Libraries
359
**Rationale**: Different projects have different linking requirements. Providing both gives maximum flexibility without requiring users to build from source.
360
361
**Alternative Considered**: Separate packages for dynamic and static. Rejected because the size overhead is minimal and user experience is worse.
362
363
### Decision 3: Platform-Specific Directory Layouts
364
**Rationale**: Following platform conventions makes integration easier for users familiar with their platform's standards. Windows expects DLLs in bin/, while Unix expects shared libraries in lib/.
365
366
**Alternative Considered**: Unified layout across all platforms. Rejected because it would be non-standard on all platforms.
367
368
### Decision 4: Reuse Existing Test Workflow
369
**Rationale**: The existing test workflow is comprehensive and already validates all target platforms. Duplicating tests would be wasteful and create maintenance burden.
370
371
**Alternative Considered**: Inline tests in release workflow. Rejected because it duplicates logic and increases workflow complexity.
372
373
### Decision 5: Matrix Build Strategy
374
**Rationale**: Building all platforms in parallel maximizes speed and allows independent failure handling. GitHub Actions provides excellent matrix support.
375
376
**Alternative Considered**: Sequential builds. Rejected because it would significantly increase release time.
377
378
### Decision 6: SHA256 Checksums
379
**Rationale**: SHA256 is the industry standard for verifying download integrity. It's widely supported and provides strong security guarantees.
380
381
**Alternative Considered**: MD5 or SHA1. Rejected because they're cryptographically weak. Multiple checksums rejected as unnecessary.
382
383
### Decision 7: Separate Checksum Files
384
**Rationale**: Separate files allow users to download and verify checksums independently. This is the standard practice for software distribution.
385
386
**Alternative Considered**: Checksums in release notes. Rejected because it's less convenient for automated verification.
387
388
### Decision 8: Tag Pattern Without 'v' Prefix
389
**Rationale**: The project already uses tags like `1.5.0` without the 'v' prefix. Maintaining consistency with existing practice is important.
390
391
**Alternative Considered**: Requiring 'v' prefix. Rejected because it would break existing tagging convention.
392
393
### Decision 9: Update Existing Release Rather Than Create
394
**Rationale**: Allowing manual release creation before the workflow runs gives maintainers control over release notes, descriptions, and other metadata. The workflow focuses on building and uploading binaries, not managing release content.
395
396
**Workflow**: 
397
1. Maintainer creates release manually with desired notes
398
2. Maintainer creates and pushes tag
399
3. Workflow builds binaries and uploads to existing release
400
4. If no release exists, workflow creates a minimal one
401
402
**Alternative Considered**: Workflow always creates release. Rejected because it forces auto-generated release notes and removes maintainer control over release presentation.