Skip to content
Merged
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
121 changes: 20 additions & 101 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,116 +1,35 @@

name: Release Binary
name: Release

on:
push:
tags:
Comment thread
leynos marked this conversation as resolved.
# Match semantic version tags (e.g. v1.2.3, v10.11.12, v12.3.7-beta7)
- 'v*.*.*'

env:
REPO_NAME: ${{ github.event.repository.name }}

jobs:
build:
goreleaser:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- os: linux
arch: x86_64
target: x86_64-unknown-linux-gnu
ext: ""
- os: linux
arch: aarch64
target: aarch64-unknown-linux-gnu
ext: ""
- os: windows
arch: x86_64
target: x86_64-pc-windows-msvc
ext: ".exe"
- os: windows
arch: aarch64
target: aarch64-pc-windows-msvc
ext: ".exe"
- os: macos
arch: x86_64
target: x86_64-apple-darwin
ext: ""
- os: macos
arch: aarch64
target: aarch64-apple-darwin
ext: ""
- os: freebsd
arch: x86_64
target: x86_64-unknown-freebsd
ext: ""
- os: freebsd
arch: aarch64
target: aarch64-unknown-freebsd
ext: ""
- os: openbsd
arch: x86_64
target: x86_64-unknown-openbsd
ext: ""
- os: openbsd
arch: aarch64
target: aarch64-unknown-openbsd
ext: ""
steps:
- uses: actions/checkout@v4
- uses: actions-rust-lang/setup-rust-toolchain@9d7e65c320fdb52dcd45ffaa68deb6c02c8754d9
with:
toolchain: stable
profile: minimal
override: true
- name: Cache cross binary
uses: actions/cache@v4
with:
path: ~/.cargo/bin/cross
key: cross-${{ runner.os }}
- name: Install cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Cache cargo registry
uses: actions/cache@v4
- name: Checkout
uses: actions/checkout@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Build release binary
run: cross +stable build --release --target ${{ matrix.target }}
- name: Prepare artifact
run: |
mkdir -p artifacts/${{ matrix.os }}-${{ matrix.arch }}
cp target/${{ matrix.target }}/release/${{ env.REPO_NAME }}${{ matrix.ext }} \
artifacts/${{ matrix.os }}-${{ matrix.arch }}/${{ env.REPO_NAME }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}
sha256sum artifacts/${{ matrix.os }}-${{ matrix.arch }}/${{ env.REPO_NAME }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} > \
artifacts/${{ matrix.os }}-${{ matrix.arch }}/${{ env.REPO_NAME }}-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}.sha256
- name: Upload release artifact
uses: actions/upload-artifact@v4
fetch-depth: 0
- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
name: ${{ env.REPO_NAME }}-${{ matrix.os }}-${{ matrix.arch }}
path: artifacts/${{ matrix.os }}-${{ matrix.arch }}

release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: softprops/action-gh-release@v1
toolchain: stable
targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu
cache: cargo
- name: Set up Go
uses: actions/setup-go@v5
with:
generate_release_notes: true
- uses: actions/download-artifact@v4
go-version: '1.21'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
path: artifacts
- run: |
for dir in artifacts/${{ env.REPO_NAME }}-*; do
for file in "$dir"/*; do
gh release upload "${{ github.ref_name }}" "$file"
done
done
distribution: goreleaser
# Use a fixed version to ensure reproducibility
version: v1.24.0
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ path = "src/lib.rs"

[dependencies]
serde = { workspace = true }
serde_yaml = { workspace = true }
serde_json = { workspace = true }

[dev-dependencies]
Expand All @@ -22,7 +23,6 @@ yaque = { workspace = true }
wiremock = "0.6"
octocrab = { workspace = true }
test-support = { path = "test-support" }
serde_yaml = "0.9"

[[test]]
name = "cucumber"
Expand All @@ -49,6 +49,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
anyhow = "1.0"
thiserror = "1.0"
ortho_config = { git = "https://github.com/leynos/ortho-config.git", tag = "v0.4.0" }
serde_yaml = "0.9"
tempfile = "3.10"

[lints.clippy]
Expand Down
17 changes: 7 additions & 10 deletions docs/automated-cross-platform-packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

This guide provides a step-by-step process for configuring a GitHub Actions
workflow to automatically build and package the `comenq` client and `comenqd`
daemon for Linux (Fedora, Ubuntu) and macOS. We will use GoReleaser to manage
the entire process, from building the Rust binaries to creating platform-native
daemon for Linux (Fedora, Ubuntu) and macOS. macOS packaging is currently on
hold, so the workflow focuses on Linux targets only. GoReleaser manages the
entire process, from building the Rust binaries to creating platform-native
packages (`.rpm`, `.deb`) and a Homebrew formula.

The core of this process involves creating a `.goreleaser.yaml` file that
Expand Down Expand Up @@ -262,7 +263,7 @@ name: Release
on:
push:
tags:
- 'v*'
- 'v[0-9]*.[0-9]*.[0-9]*'

jobs:
goreleaser:
Expand All @@ -277,23 +278,19 @@ jobs:
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-apple-darwin, aarch64-apple-darwin
targets: x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu
cache: cargo

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Install GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
install-only: true

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser
version: latest
version: v1.24.0
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
4 changes: 3 additions & 1 deletion docs/comenq-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,9 @@ To simplify installation, the project uses GoReleaser. The declarative
hooks. The `nfpms` section produces signed `.deb` and `.rpm` packages for
Fedora and Ubuntu, embedding the hardened `systemd` service unit and lifecycle
scripts that create the `comenq` user. This keeps packaging logic version
controlled and repeatable.
controlled and repeatable. A GitHub Actions workflow triggers on version tags
to run GoReleaser. It builds Linux packages and uploads them to a draft
release. Mac support is currently deferred, so the workflow targets Linux only.

## Section 5: Complete Source Code and Project Manifest

Expand Down
8 changes: 4 additions & 4 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,15 @@ and macOS, simplifying installation and improving security and maintainability.
- [x] Configure GoReleaser's `nfpms` section to build and sign `.rpm` and
`.deb` packages.

- [ ] **Automate the Release Workflow**
- [x] **Automate the Release Workflow**

- [ ] Implement a GitHub Actions workflow that triggers on new version tags
- [x] Implement a GitHub Actions workflow that triggers on new version tags
(e.g., `v*`).

- [ ] The workflow will orchestrate the entire release: checking out the
- [x] The workflow will orchestrate the entire release: checking out the
code, installing dependencies, and executing GoReleaser.

- [ ] GoReleaser will then build the binaries, create all packages, publish
- [x] GoReleaser will then build the binaries, create all packages, publish
the Homebrew formula, generate a changelog from git history, and upload all
assets to a draft GitHub Release.

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! and daemon.

use serde::{Deserialize, Serialize};
pub mod workflow;

/// Request sent from the client to the daemon.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
Expand Down
59 changes: 59 additions & 0 deletions src/workflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Utilities for inspecting GitHub workflow files.

use serde_yaml::Value;

/// Return `true` if the workflow steps include the `GoReleaser` action.
///
/// # Errors
///
/// Returns an error if the YAML cannot be parsed.
pub fn uses_goreleaser(yaml: &str) -> Result<bool, serde_yaml::Error> {
let doc: Value = serde_yaml::from_str(yaml)?;
let Some(jobs) = doc.get("jobs") else {
return Ok(false);
};
let Some(map) = jobs.as_mapping() else {
return Ok(false);
};
for job in map.values() {
let Some(steps) = job.get("steps") else {
continue;
};
let Some(arr) = steps.as_sequence() else {
continue;
};
for step in arr {
if step
.get("uses")
.and_then(|u| u.as_str())
.is_some_and(|s| s.starts_with("goreleaser/goreleaser-action"))
{
return Ok(true);
}
}
}
Ok(false)
}

#[cfg(test)]
mod tests {
#![expect(clippy::expect_used, reason = "simplify test output")]
Comment thread
leynos marked this conversation as resolved.
use super::uses_goreleaser;

#[test]
fn detects_goreleaser() {
let yaml = r"
jobs:
goreleaser:
steps:
- uses: goreleaser/goreleaser-action@v5
";
assert!(uses_goreleaser(yaml).expect("parse"));
}

#[test]
fn missing_goreleaser() {
let yaml = "jobs: {}";
assert!(!uses_goreleaser(yaml).expect("parse"));
}
}
4 changes: 3 additions & 1 deletion tests/cucumber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ mod support;
mod util;
use cucumber::World as _;
use steps::{
CliWorld, ClientWorld, CommentWorld, ConfigWorld, ListenerWorld, PackagingWorld, WorkerWorld,
CliWorld, ClientWorld, CommentWorld, ConfigWorld, ListenerWorld, PackagingWorld, ReleaseWorld,
WorkerWorld,
};

#[tokio::main]
async fn main() {
tokio::join!(
CliWorld::run("tests/features/cli.feature"),
ReleaseWorld::run("tests/features/release.feature"),
ClientWorld::run("tests/features/client_main.feature"),
CommentWorld::run("tests/features/comment_request.feature"),
ConfigWorld::run("tests/features/config.feature"),
Expand Down
11 changes: 11 additions & 0 deletions tests/features/release.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: Release workflow
Comment thread
leynos marked this conversation as resolved.

Scenario: goreleaser step present
Given the release workflow file
When it is parsed as YAML
Then the workflow uses goreleaser

Scenario: triggers on version tags
Given the release workflow file
When it is parsed as YAML
Then the workflow triggers on tags
6 changes: 4 additions & 2 deletions tests/steps/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod client_main_steps;
pub use client_main_steps::ClientWorld;
pub mod cli_steps;
pub use cli_steps::CliWorld;
pub mod client_main_steps;
pub use client_main_steps::ClientWorld;
pub mod comment_steps;
pub use comment_steps::CommentWorld;
pub mod config_steps;
Expand All @@ -10,5 +10,7 @@ pub mod listener_steps;
pub use listener_steps::ListenerWorld;
pub mod packaging_steps;
pub use packaging_steps::PackagingWorld;
pub mod release_steps;
pub use release_steps::ReleaseWorld;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
pub mod worker_steps;
pub use worker_steps::WorkerWorld;
Loading