Skip to content

feat: add Homebrew, container image, and install script distribution#7

Merged
pavelanni merged 2 commits intomainfrom
feature/distribution
Apr 22, 2026
Merged

feat: add Homebrew, container image, and install script distribution#7
pavelanni merged 2 commits intomainfrom
feature/distribution

Conversation

@pavelanni
Copy link
Copy Markdown
Collaborator

@pavelanni pavelanni commented Apr 21, 2026

Summary

  • Add Homebrew formula via GoReleaser, auto-updated to pavelanni/homebrew-tap on each release
  • Add multi-arch container image (ghcr.io/redhat-et/skillctl) built from a minimal scratch-based Dockerfile
  • Add install.sh — a curl-based installer that detects OS/arch and downloads from GitHub Releases
  • Update release workflow with GHCR login and Homebrew tap token passthrough
  • Update README with install section covering all five distribution methods

Setup required before first release

  1. Create pavelanni/homebrew-tap repo on GitHub (empty, public)
  2. Create a GitHub PAT with repo scope for that repo
  3. Add it as HOMEBREW_TAP_TOKEN secret in redhat-et/skillimage settings

Test plan

  • goreleaser check validates config
  • make test and make lint pass
  • Manual: goreleaser release --snapshot --clean to verify archives, Docker images, and formula generation
  • Manual: verify install.sh works after first release
  • Manual: verify brew install pavelanni/tap/skillctl works after first release

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Homebrew formula for easy installation.
    • New curl-based installation script for streamlined setup across platforms.
    • Multi-architecture Docker images now available on GitHub Container Registry (amd64 and arm64).
  • Documentation

    • Expanded README with comprehensive installation guide covering multiple methods: Homebrew, curl script, Go install, container, and pre-built binaries.

Add multiple distribution channels for skillctl:

- Homebrew: GoReleaser auto-updates pavelanni/homebrew-tap on release
- Container: multi-arch image (amd64/arm64) pushed to ghcr.io/redhat-et/skillctl
- Install script: curl-based installer that detects OS/arch
- go install: documented in README (works today, zero effort)
- GitHub Releases: already configured, now documented in README

Release workflow updated with GHCR login (packages:write) and
HOMEBREW_TAP_TOKEN secret passthrough.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Pavel Anni <panni@redhat.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Warning

Rate limit exceeded

@pavelanni has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes and 34 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 50 minutes and 34 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1758bc87-c217-400b-bfcf-1f65ea41dd60

📥 Commits

Reviewing files that changed from the base of the PR and between ba9f4c7 and abf4f0d.

📒 Files selected for processing (3)
  • Dockerfile
  • README.md
  • install.sh
📝 Walkthrough

Walkthrough

This change adds comprehensive release distribution infrastructure for the skillctl project, including automated Docker image building and publishing to GitHub Container Registry, Homebrew formula publication, a curl-installable shell script, and updated documentation with multiple installation methods.

Changes

Cohort / File(s) Summary
Release Automation
.github/workflows/release.yaml, .goreleaser.yaml
Added Docker Buildx setup and GHCR login to workflow; configured GoReleaser with Homebrew tap publishing (via HOMEBREW_TAP_TOKEN) and Docker multi-architecture image builds and manifests targeting linux/amd64 and linux/arm64.
Container Distribution
Dockerfile
Multi-stage build using Alpine for CA certificate extraction, final scratch-based runtime image with minimal footprint; entrypoint runs skillctl binary directly.
Installation & Documentation
README.md, install.sh
Added "Install" section with Homebrew, curl script, go install, container, and source build options; new install.sh script detects OS/architecture, resolves release version from env or GitHub API, downloads and installs binary with privilege escalation when needed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding Homebrew distribution, container image support, and an install script. All three distribution methods mentioned are present in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/distribution

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pavelanni pavelanni marked this pull request as ready for review April 21, 2026 18:56
@pavelanni
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

✅ 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

@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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Dockerfile`:
- Around line 4-7: The image currently runs ENTRYPOINT ["skillctl"] as root; add
a non-root user and switch to it using USER to remediate DS-0002. Update the
Dockerfile to create a user (e.g., addgroup/adduser or useradd with a fixed
non-root UID like 1000), ensure /usr/local/bin/skillctl is owned and executable
by that user (chown/chmod), and place the USER <username-or-uid> line before
ENTRYPOINT so skillctl runs unprivileged.

In `@install.sh`:
- Around line 53-60: The chmod +x is executed without sudo even when mv used
sudo, causing permission failures; move the chmod step into the same if/else
that performs mv so it runs under the same privilege level. In the block that
checks [ -w "$INSTALL_DIR" ] and calls mv "${TMPDIR}/${BINARY}"
"${INSTALL_DIR}/${BINARY}", add chmod +x "${INSTALL_DIR}/${BINARY}" there, and
in the else branch that uses sudo mv use sudo chmod +x
"${INSTALL_DIR}/${BINARY}" so ownership and permissions are set with matching
privileges for INSTALL_DIR, BINARY, and TMPDIR.
- Around line 47-51: Add checksum verification before extracting the downloaded
archive: after downloading "${TMPDIR}/${ARCHIVE}" and before tar -xzf, fetch the
release's checksums file (e.g., checksums.txt) from the same URL base, compute
the archive's SHA-256 digest (using shasum -a 256 or sha256sum) and compare it
against the expected entry for "${ARCHIVE}" in the checksums file; if the
checksum lookup or comparison fails, log an error and exit nonzero instead of
extracting. Use the existing variables (BINARY, VERSION, OS, ARCH, TMPDIR,
ARCHIVE, URL) to locate both the archive and checksums file and make the script
robust to missing tools or mismatches by handling errors and failing fast.

In `@README.md`:
- Around line 39-42: The installer env vars are currently applied only to curl;
change the README command so VERSION and INSTALL_DIR are passed to the shell
that executes the piped script (e.g., invoke sh with the env vars or use env to
set VERSION and INSTALL_DIR before sh and include the -s/-- to ensure the script
reads from stdin); update the example command in README.md so the installer
receives VERSION and INSTALL_DIR instead of only curl.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 00fa4bf0-ac59-478a-8413-4878cda901cd

📥 Commits

Reviewing files that changed from the base of the PR and between 443ec21 and ba9f4c7.

📒 Files selected for processing (5)
  • .github/workflows/release.yaml
  • .goreleaser.yaml
  • Dockerfile
  • README.md
  • install.sh

Comment thread Dockerfile
Comment thread install.sh
Comment thread install.sh Outdated
Comment thread README.md
- Dockerfile: run as non-root (UID 65534) instead of root
- install.sh: verify SHA-256 checksum before extracting archive
- install.sh: match chmod privilege level with mv (sudo when needed)
- README: pass VERSION/INSTALL_DIR to sh, not curl

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Pavel Anni <panni@redhat.com>
@pavelanni pavelanni merged commit 6e2004d into main Apr 22, 2026
6 checks passed
@pavelanni pavelanni deleted the feature/distribution branch April 22, 2026 00:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant