Skip to content

Implement packaging with GoReleaser#24

Merged
leynos merged 3 commits intomainfrom
codex/implement-automated-packaging-with-goreleaser
Jul 31, 2025
Merged

Implement packaging with GoReleaser#24
leynos merged 3 commits intomainfrom
codex/implement-automated-packaging-with-goreleaser

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jul 30, 2025

Summary

  • add .goreleaser.yaml with Linux builds and nfpms packaging
  • provide hardened systemd unit and install scripts
  • include default daemon config and launchd plist
  • document packaging design and mark roadmap tasks done
  • test packaging configuration with new behavioural scenarios

Testing

  • make fmt
  • make lint
  • make test
  • make markdownlint

https://chatgpt.com/codex/tasks/task_e_68896fb9b50c83228861d62848d0065c

Summary by Sourcery

Implement a declarative, cross-platform packaging workflow using GoReleaser for Linux and macOS, complete with service units, install scripts, default configs, behavioural tests, and updated documentation

New Features:

  • Add GoReleaser configuration to build and package comedq and comenq binaries into signed .deb and .rpm on Linux and generate a Homebrew formula for macOS

Enhancements:

  • Provide hardened systemd unit and lifecycle scripts for Linux packaging
  • Include launchd plist and default configuration files for macOS packaging
  • Integrate packaging behavioural tests using Cucumber and serde_yaml

Documentation:

  • Add and update documentation for automated cross-platform packaging and mark relevant roadmap items complete

Tests:

  • Introduce Cucumber feature and step definitions to verify GoReleaser configuration and service hardening

Chores:

  • Add serde_yaml dependency to support YAML parsing in packaging tests

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Jul 30, 2025

Reviewer's Guide

Automates cross-platform packaging with GoReleaser by adding a declarative .goreleaser.yaml, updating the GitHub Actions release workflow, introducing hardened Linux systemd units and macOS launchd plist with install scripts, updating documentation, and adding Cucumber tests to validate packaging configuration.

File-Level Changes

Change Details Files
Add GoReleaser packaging configuration
  • Introduce .goreleaser.yaml with builds, archives, nfpms, release and changelog sections
  • Update GitHub Actions workflow to call GoReleaser on new version tags
  • Add serde_yaml dependency to Cargo.toml for YAML parsing in tests
.goreleaser.yaml
.github/workflows/release.yml
Cargo.toml
Implement Linux packaging assets
  • Add hardened systemd unit file with security directives
  • Create preinstall, postinstall, and preremove scripts for user/group setup and service lifecycle
  • Include default daemon configuration file in package contents
packaging/linux/comenqd.service
packaging/linux/preinstall.sh
packaging/linux/postinstall.sh
packaging/linux/preremove.sh
packaging/comenqd/config.toml
Add macOS packaging support
  • Provide a launchd plist for managing the daemon on macOS
  • Configure Homebrew formula generation in the brews section of .goreleaser.yaml
  • Ensure default configuration is packaged for macOS
packaging/darwin/comenqd.plist
.goreleaser.yaml
Update documentation for packaging workflow
  • Revise automated-cross-platform-packaging guide with step-by-step instructions
  • Mark GoReleaser and Linux packaging tasks as completed in roadmap
  • Document packaging and release workflow in design docs
docs/automated-cross-platform-packaging.md
docs/roadmap.md
docs/comenq-design.md
Add Cucumber tests for packaging validation
  • Import PackagingWorld and steps in the cucumber test runner
  • Define packaging_steps.rs with YAML parsing and unit hardening checks
  • Add packaging.feature scenarios verifying nfpms section and service hardening
tests/cucumber.rs
tests/steps/mod.rs
tests/steps/packaging_steps.rs
tests/features/packaging.feature

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 30, 2025

Summary by CodeRabbit

New Features

  • Introduced automated build and packaging for Linux and macOS, including systemd and launchd service files.
  • Added default configuration templates and lifecycle scripts for improved deployment.

Documentation

  • Updated and expanded packaging and release workflow documentation.
  • Improved clarity and formatting in packaging and roadmap guides.

Tests

  • Added behavioural tests to verify packaging configuration and service hardening.

Chores

  • Integrated GoReleaser configuration and enhanced development dependencies.

Walkthrough

Introduce automated packaging and release infrastructure for the "comenq" project using GoReleaser with Rust integration. Add systemd and launchd service definitions, lifecycle shell scripts, and default configuration files. Expand documentation to explain packaging, update the roadmap, and implement Cucumber-based behavioural tests to verify packaging artefacts and hardening.

Changes

Cohort / File(s) Change Summary
GoReleaser Configuration & Packaging
.goreleaser.yaml, packaging/comenqd/config.toml, packaging/darwin/comenqd.plist, packaging/linux/comenqd.service, packaging/linux/postinstall.sh, packaging/linux/preinstall.sh, packaging/linux/preremove.sh
Add GoReleaser config for Rust binaries, systemd and launchd service files, default config, and lifecycle scripts for Linux/macOS packaging.
Documentation
docs/automated-cross-platform-packaging.md, docs/comenq-design.md, docs/roadmap.md
Reformat, clarify, and expand documentation. Add packaging workflow details, mark roadmap packaging tasks as complete, and improve error handling in install scripts.
Rust Project & Dependencies
Cargo.toml
Add serde_yaml as a dev-dependency for YAML parsing in tests.
Test Infrastructure
tests/cucumber.rs, tests/features/packaging.feature, tests/steps/mod.rs, tests/steps/packaging_steps.rs
Add Cucumber feature and step definitions to validate packaging files, YAML config, and systemd hardening. Expose new test world for packaging.

Sequence Diagram(s)

sequenceDiagram
    participant Developer
    participant GoReleaser
    participant Cargo
    participant Systemd
    participant OS Package Manager

    Developer->>GoReleaser: Trigger release
    GoReleaser->>Cargo: Build comenq/comenqd binaries
    Cargo-->>GoReleaser: Provide binaries
    GoReleaser->>GoReleaser: Package with config, service files, scripts
    GoReleaser->>OS Package Manager: Produce .deb/.rpm packages
    OS Package Manager->>Systemd: Install service, run pre/post scripts
    Systemd-->>Developer: Service enabled & running
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🛠️
Release the code, let binaries fly,
With scripts and configs standing by.
Systemd guards in hardened might,
Cucumber tests confirm all’s right.
Docs now gleam, the roadmap’s on track—
Comenq’s packages ready to unpack!
🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0620c and 612c43b.

📒 Files selected for processing (7)
  • docs/automated-cross-platform-packaging.md (9 hunks)
  • docs/comenq-design.md (1 hunks)
  • packaging/comenqd/config.toml (1 hunks)
  • packaging/linux/postinstall.sh (1 hunks)
  • packaging/linux/preinstall.sh (1 hunks)
  • tests/steps/mod.rs (1 hunks)
  • tests/steps/packaging_steps.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • tests/steps/mod.rs
  • tests/steps/packaging_steps.rs
**/*.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/comenq-design.md
  • docs/automated-cross-platform-packaging.md
🔇 Additional comments (18)
tests/steps/mod.rs (1)

11-12: LGTM on the module integration.

The packaging_steps module is correctly declared and PackagingWorld is properly re-exported for use in the test framework.

packaging/linux/postinstall.sh (1)

1-9: Excellent systemd service lifecycle management.

The script properly guards systemctl operations behind systemd availability checks and uses robust error handling. This ensures idempotent behavior across different environments.

docs/comenq-design.md (1)

717-725: Comprehensive packaging documentation adds significant value.

The new subsection thoroughly documents the GoReleaser workflow, packaging outputs, and integration with the existing deployment strategy. Well-structured and informative.

packaging/linux/preinstall.sh (1)

19-22: Remove redundant ownership and permission operations.

Line 19 already sets ownership (-o comenq -g comenq) and permissions (-m 750) via the install command. Lines 21-22 duplicate these operations unnecessarily.

Apply this diff to eliminate redundancy:

 install -d -o comenq -g comenq -m 750 /var/lib/comenq
-
-chown -R comenq:comenq /var/lib/comenq
-chmod 750 /var/lib/comenq
⛔ Skipped due to learnings
Learnt from: CR
PR: leynos/comenq#0
File: docs/comenq-design.md:0-0
Timestamp: 2025-07-27T00:57:37.611Z
Learning: Create and set ownership of `/var/lib/comenq` and `/run/comenq` directories to the `comenq` user and group for daemon state and socket files.
tests/steps/packaging_steps.rs (6)

1-3: LGTM! Proper module documentation and lint handling.

The module doc comment clearly explains the purpose, and the narrowly scoped #[expect] with a clear reason follows the coding guidelines correctly.


4-12: LGTM! Clean imports and well-designed test world struct.

The struct appropriately uses Option types for state management and derives the necessary traits for Cucumber integration.


14-18: LGTM! Simple and focused file reading step.

The function adheres to single responsibility and uses appropriate error handling for test code.


20-24: LGTM! Correct state transformation pattern.

The use of .take() here is appropriate as this step transforms raw content into parsed YAML, consuming the original state.


26-30: LGTM! Properly addressed state consumption issue.

The use of .as_ref() correctly preserves the world state for potential reuse, addressing the previous review feedback appropriately.


32-44: Merge now that tests and service file path are verified

  • packaging/linux/comenqd.service exists as expected.

Proceed without further changes.

docs/automated-cross-platform-packaging.md (8)

1-14: LGTM! Proper document structure and formatting.

The heading hierarchy and British English usage follow the coding guidelines correctly.


15-89: LGTM! Comprehensive systemd service configuration with proper hardening.

The systemd unit file includes essential security hardening directives that align with modern best practices. The documentation clearly explains the purpose of each security measure.


90-202: LGTM! Comprehensive and technically accurate GoReleaser configuration.

The configuration properly handles Rust builds, package metadata, and Linux distribution packaging. The YAML structure is well-formatted and follows GoReleaser best practices.


203-250: LGTM! Robust shell scripts with proper error handling.

The lifecycle scripts demonstrate excellent practices with strict error handling (set -euo pipefail), proper system user creation, and correct systemd service management.


251-301: LGTM! Well-structured GitHub Actions workflow.

The workflow includes all necessary setup steps, proper cross-compilation targets, and follows GitHub Actions best practices for release automation.


302-412: LGTM! Comprehensive macOS packaging configuration.

The launchd plist format is correct, and the Homebrew tap configuration follows proper conventions. The documentation clearly explains macOS-specific requirements.


413-526: LGTM! Complete and consistent final configuration.

The consolidated GoReleaser configuration properly combines all previous examples and maintains consistency across Linux and macOS packaging requirements.


527-547: LGTM! Clear and comprehensive setup instructions.

The final steps provide all necessary information for users to implement the automated packaging workflow, including proper security token setup and release process.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/implement-automated-packaging-with-goreleaser

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @leynos - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `packaging/linux/preinstall.sh:2` </location>
<code_context>
+#!/bin/bash
+if ! getent group comenq >/dev/null; then
+    groupadd --system comenq
+fi
+if ! getent passwd comenq >/dev/null; then
</code_context>

<issue_to_address>
Check for errors when creating group and user.

Currently, failures from `groupadd` or `useradd` are ignored, which may cause inconsistent system state. Add error handling to exit if these commands fail.
</issue_to_address>

### Comment 2
<location> `packaging/linux/preinstall.sh:5` </location>
<code_context>
+if ! getent group comenq >/dev/null; then
+    groupadd --system comenq
+fi
+if ! getent passwd comenq >/dev/null; then
+    useradd --system --gid comenq --home-dir /var/lib/comenq --create-home --shell /sbin/nologin comenq
+fi
</code_context>

<issue_to_address>
Explicitly set ownership and permissions for the home directory.

Ensure the home directory is owned by the 'comenq' user and group, and set secure permissions to prevent unauthorized access.
</issue_to_address>

### Comment 3
<location> `packaging/linux/postinstall.sh:3` </location>
<code_context>
+#!/bin/bash
+systemctl daemon-reload
+systemctl enable comenqd.service
+systemctl start comenqd.service
</code_context>

<issue_to_address>
Consider handling failures in systemctl commands.

Currently, if a systemctl command fails, the script continues without notifying the user. Adding error handling or 'set -e' will ensure the script aborts on failure and alerts the user to installation issues.
</issue_to_address>

### Comment 4
<location> `packaging/linux/preremove.sh:2` </location>
<code_context>
+#!/bin/bash
+systemctl stop comenqd.service
+systemctl disable comenqd.service
</code_context>

<issue_to_address>
Handle cases where the service is not running or enabled.

Consider suppressing non-critical errors with `|| true`, or check for the service's existence before running these commands.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread packaging/linux/preinstall.sh Outdated
Comment thread packaging/linux/preinstall.sh Outdated
Comment thread packaging/linux/postinstall.sh Outdated
Comment thread packaging/linux/preremove.sh Outdated
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 31, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 31, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (2)
Cargo.toml (1)

4-4: Target the latest stable Rust edition, not 2024.

edition = "2024" requires a nightly toolchain that many CI/CD and users will not yet have. Stick to 2021 until the 2024 edition is officially stabilised or explicitly document the nightly requirement.

packaging/darwin/comenqd.plist (1)

1-23: Consider adding user specification and log directory creation.

The plist configuration is well-formed but lacks user specification (will run as root) and assumes log directories exist. Add security hardening where possible.

Consider these improvements:

 <dict>
     <key>Label</key>
     <string>com.github.leynos.comenqd</string>
+    <key>UserName</key>
+    <string>_comenq</string>
+    <key>GroupName</key>
+    <string>_comenq</string>
     <key>ProgramArguments</key>
     <array>
         <string>/usr/local/bin/comenqd</string>
         <string>--config</string>
         <string>/usr/local/etc/comenq/config.toml</string>
     </array>
     <key>RunAtLoad</key>
     <true/>
     <key>KeepAlive</key>
     <true/>
+    <key>StandardOutPath</key>
+    <string>/usr/local/var/log/comenq/comenqd.log</string>
+    <key>StandardErrorPath</key>
+    <string>/usr/local/var/log/comenq/comenqd.err</string>
 </dict>

Ensure log directories are created during installation and consider using a dedicated user account for improved security.

♻️ Duplicate comments (1)
packaging/linux/preremove.sh (1)

4-10: Handle systemctl command failures gracefully to prevent package removal issues.

The script uses set -euo pipefail which will cause it to exit on any systemctl error, potentially blocking package removal if the service is in an unexpected state. Add error suppression for non-critical cases.

Apply this diff to handle edge cases gracefully:

-if systemctl is-active --quiet comenqd.service; then
-    systemctl stop comenqd.service
+if systemctl is-active --quiet comenqd.service 2>/dev/null; then
+    systemctl stop comenqd.service || true
 fi
 
-if systemctl is-enabled --quiet comenqd.service; then
-    systemctl disable comenqd.service
+if systemctl is-enabled --quiet comenqd.service 2>/dev/null; then
+    systemctl disable comenqd.service || true
 fi
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3636844 and 5d0620c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • .goreleaser.yaml (1 hunks)
  • Cargo.toml (1 hunks)
  • docs/automated-cross-platform-packaging.md (10 hunks)
  • docs/comenq-design.md (1 hunks)
  • docs/roadmap.md (1 hunks)
  • packaging/comenqd/config.toml (1 hunks)
  • packaging/darwin/comenqd.plist (1 hunks)
  • packaging/linux/comenqd.service (1 hunks)
  • packaging/linux/postinstall.sh (1 hunks)
  • packaging/linux/preinstall.sh (1 hunks)
  • packaging/linux/preremove.sh (1 hunks)
  • tests/cucumber.rs (2 hunks)
  • tests/features/packaging.feature (1 hunks)
  • tests/steps/mod.rs (1 hunks)
  • tests/steps/packaging_steps.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • tests/steps/mod.rs
  • tests/cucumber.rs
  • tests/steps/packaging_steps.rs
**/*.md

⚙️ CodeRabbit Configuration File

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/roadmap.md
  • docs/comenq-design.md
  • docs/automated-cross-platform-packaging.md
🧠 Learnings (1)
📚 Learning: applies to docs/**/comenq.service : configure the service to run as the `comenq` user, restart on fa...
Learnt from: CR
PR: leynos/comenq#0
File: docs/roadmap.md:0-0
Timestamp: 2025-07-27T00:57:51.356Z
Learning: Applies to docs/**/comenq.service : Configure the service to run as the `comenq` user, restart on failure, and include security hardening directives (`ProtectSystem`, `PrivateTmp`, etc.).

Applied to files:

  • packaging/linux/comenqd.service
🪛 LanguageTool
docs/comenq-design.md

[uncategorized] ~719-~719: Possible missing comma found.
Context: ...aging and Release Workflow To simplify installation the project uses GoReleaser. The declar...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (14)
tests/features/packaging.feature (1)

1-11: LGTM! Well-structured packaging validation tests.

The feature scenarios effectively validate critical packaging components: GoReleaser configuration parsing and systemd hardening directives. The Gherkin syntax is clean and the test scope is appropriately focused.

tests/cucumber.rs (2)

3-5: LGTM! Proper integration of packaging test suite.

The addition of PackagingWorld to the imports and test execution follows the established pattern correctly.


15-15: LGTM! Test execution properly integrated.

The packaging feature test is correctly added to the concurrent test execution.

docs/roadmap.md (1)

84-107: LGTM: Milestone completion accurately documented.

The roadmap updates correctly reflect the completed packaging implementation tasks, and the line wrapping adheres to the 80-column guideline for Markdown files.

packaging/linux/comenqd.service (1)

1-24: Excellent security hardening implementation.

The systemd service unit file implements comprehensive security hardening with appropriate capability restrictions, filesystem protections, and privilege controls. The service configuration correctly runs as the dedicated comenq user and includes proper restart behaviour.

.goreleaser.yaml (3)

34-64: LGTM: Comprehensive packaging configuration.

The nfpm configurations properly separate client and daemon packages, include necessary systemd service files and lifecycle scripts, and follow packaging best practices. The daemon package correctly includes the hardened service unit and configuration files.


71-80: Well-configured changelog filtering.

The changelog configuration appropriately excludes development commits and merge messages while maintaining ascending chronological order.


9-23: Verify Rust target triples in GoReleaser hooks

The {{ .TARGET }} variable emits Go’s OS/Arch (e.g. linux_amd64), not Rust’s target triples. Update both build hooks in .goreleaser.yaml to map .Os/.Arch to the correct Rust triples:

• File: .goreleaser.yaml

  • Lines 9–23 (builds for comenq and comenqd)
    hooks:
      pre:
-       - cmd: cargo build --release --package comenq --target {{ .TARGET }}
+       - cmd: |
+           case "{{ .Os }}_{{ .Arch }}" in
+             linux_amd64) TARGET="x86_64-unknown-linux-gnu";;
+             linux_arm64) TARGET="aarch64-unknown-linux-gnu";;
+             *) echo "Unsupported target" && exit 1;;
+           esac
+           cargo build --release --package comenq --target $TARGET

Apply the same patch under the comenqd build hook. Test locally to confirm these mappings.

tests/steps/packaging_steps.rs (2)

1-12: Well-structured test module with proper documentation.

The module follows Rust coding guidelines with appropriate module documentation, proper lint expectations, and a clear World struct for test state management.


38-44: Comprehensive hardening verification.

The test properly verifies the presence of key systemd hardening directives that align with security best practices.

docs/automated-cross-platform-packaging.md (4)

1-14: LGTM: Well-structured documentation introduction.

The documentation follows Markdown guidelines with proper heading hierarchy, 80-column wrapping, and clear introductory content.


102-125: Flag inconsistency with actual implementation.

The documentation example shows builds targeting both linux and darwin, but the actual .goreleaser.yaml file only targets linux for both builds. Update the documentation to match the implementation or expand the actual configuration.

Apply this diff to align with the actual implementation:

     goos: [linux, darwin]
+    # Note: Current implementation targets Linux only
+    goos: [linux]

Likely an incorrect or invalid review comment.


208-220: Excellent error handling in installation scripts.

The shell scripts properly use set -euo pipefail for strict error handling and include appropriate error reporting for user/group creation operations.


236-245: Robust service management in preremove script.

The conditional checks for service state before stopping/disabling prevent errors during package removal and follow systemd best practices.

Comment thread Cargo.toml
Comment thread docs/comenq-design.md
Comment thread packaging/comenqd/config.toml
Comment thread packaging/linux/postinstall.sh Outdated
Comment thread packaging/linux/preinstall.sh
Comment thread packaging/linux/preinstall.sh Outdated
Comment thread tests/steps/mod.rs
Comment thread tests/steps/packaging_steps.rs
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 31, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 31, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link
Copy Markdown

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 31, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 31, 2025

@coderabbitai review

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Jul 31, 2025

@sourcery-ai review

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @leynos - I've reviewed your changes and found some issues that need to be addressed.

  • Cargo.toml adds serde_yaml as a normal dependency but it’s only used in tests—move it to dev-dependencies to avoid shipping it in production builds.
  • Instead of using the GoReleaser Go builder with manual cargo hooks, consider the goreleaser-rust plugin or Docker-based builds to streamline cross-compiling Rust binaries.
  • The packaging directory duplicates configuration files for Linux and macOS—extracting a shared config template would reduce duplication and simplify updates.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Cargo.toml adds serde_yaml as a normal dependency but it’s only used in tests—move it to dev-dependencies to avoid shipping it in production builds.
- Instead of using the GoReleaser Go builder with manual cargo hooks, consider the goreleaser-rust plugin or Docker-based builds to streamline cross-compiling Rust binaries.
- The packaging directory duplicates configuration files for Linux and macOS—extracting a shared config template would reduce duplication and simplify updates.

## Individual Comments

### Comment 1
<location> `packaging/linux/preremove.sh:4` </location>
<code_context>
 # Stop and disable the service before removal.
-systemctl stop comenqd.service
-systemctl disable comenqd.service
+if systemctl is-active --quiet comenqd.service; then
+    systemctl stop comenqd.service
+fi
+if systemctl is-enabled --quiet comenqd.service; then
</code_context>

<issue_to_address>
Consider handling errors if systemctl is not available.

Add a check to verify systemctl is available before running these commands, as done in postinstall.sh.
</issue_to_address>

### Comment 2
<location> `packaging/comenqd/config.toml:4` </location>
<code_context>
 ```toml
 # Default configuration for comenqd
-# Example:
+# github_token = ""
 # log_level = "info"
+# socket_path = "/run/comenq/comenq.sock"
</code_context>

<issue_to_address>
Clarify if empty github_token disables GitHub integration.

Please document whether an empty github_token disables integration or triggers an error to prevent confusion.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
# GitHub Personal Access Token used for authentication
# github_token = ""
=======
# GitHub Personal Access Token used for authentication.
# If left empty, GitHub integration is disabled.
# github_token = ""
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread packaging/linux/preremove.sh
Comment thread packaging/comenqd/config.toml
@leynos leynos merged commit 981a8d1 into main Jul 31, 2025
1 check passed
@leynos leynos deleted the codex/implement-automated-packaging-with-goreleaser branch July 31, 2025 21:08
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 31, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant