From 92c022b0d4af16eeb934bd9b96d484392fedefe1 Mon Sep 17 00:00:00 2001 From: Paulo Fidalgo Date: Fri, 17 Jul 2026 10:44:48 +0100 Subject: [PATCH 1/2] docs(repo): prepare first public release Document installation, configuration, troubleshooting, contribution, security, conduct, and maintainer release procedures for the public gem. Refresh checkout hardening, point package metadata at the live repository, and record the complete 0.1.0 release surface without adding one-off release automation. --- .github/workflows/changelog.yml | 3 +- .github/workflows/commitlint.yml | 3 +- .github/workflows/release.yml | 4 +- .github/workflows/ruby.yml | 7 ++- CHANGELOG.md | 4 ++ CODE_OF_CONDUCT.md | 30 ++++++++++++ CONTRIBUTING.md | 50 ++++++++++++++++++++ README.md | 75 ++++++++++++++++++++---------- SECURITY.md | 34 ++++++++++++++ docs/releasing.md | 79 ++++++++++++++++++++++++++++++++ ruby_llm-codex.gemspec | 2 +- 11 files changed, 259 insertions(+), 32 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md create mode 100644 docs/releasing.md diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 8d9ae45..b172ad0 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -10,9 +10,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 + persist-credentials: false - name: Validate git-cliff changelog generation uses: orhun/git-cliff-action@v4 diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 9d0fd4b..32eaf96 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -9,9 +9,10 @@ jobs: commitlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 + persist-credentials: false - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d5944d1..ea5e627 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,10 +18,10 @@ jobs: id-token: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} + persist-credentials: false - name: Set up Ruby uses: ruby/setup-ruby@v1 diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 0d08c20..f426bd9 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -18,7 +18,9 @@ jobs: ruby-version: ["3.1.3", "3.4", "4.0.3"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + with: + persist-credentials: false - name: Set up Ruby uses: ruby/setup-ruby@v1 @@ -33,9 +35,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 + persist-credentials: false - name: Validate git-cliff changelog generation uses: orhun/git-cliff-action@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 45cc209..0b4d7ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 experiments. - Add isolated execution defaults, timeout handling, and process-group cleanup. - Add live smoke coverage for plain-text and structured-output requests. +- Add CI, Conventional Commit checks, changelog validation, and tag-driven + RubyGems trusted publishing. +- Document installation, configuration, limitations, troubleshooting, + contribution, security, and release procedures. ### Fixed diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..bcc196c --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,30 @@ +# Code of Conduct + +## Our standard + +We are committed to a welcoming, respectful, and harassment-free community. +Examples of positive behavior include empathy, constructive feedback, respect +for differing viewpoints, and taking responsibility for mistakes. + +Unacceptable behavior includes harassment, discriminatory language, personal +attacks, deliberate intimidation, publishing another person's private +information, or conduct that would reasonably be considered inappropriate in a +professional setting. + +## Enforcement + +Project maintainers may remove, edit, or reject comments, commits, issues, and +other contributions that violate this standard. They may temporarily or +permanently restrict participation when necessary to protect the community. + +Report conduct concerns privately to `devel@ethos-link.com`. Maintainers will +respect the reporter's privacy and evaluate reports fairly. Retaliation against +someone who reports a concern is prohibited. + +## Scope + +This policy applies in project spaces and when an individual is publicly +representing the project or its community. + +This policy is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1ea6ff6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,50 @@ +# Contributing + +Thank you for helping improve `ruby_llm-codex`. + +## Before opening a change + +- Use an issue for user-visible behavior changes or proposals that need design + agreement. +- Use [GitHub's private vulnerability reporting](SECURITY.md) for security + issues; do not disclose them publicly. +- Keep the adapter's scope narrow: non-streaming RubyLLM chat through the local + Codex CLI, with isolation and reproducibility as defaults. + +## Development setup + +```bash +git clone git@github.com:ethos-link/ruby_llm-codex.git +cd ruby_llm-codex +bundle install +bundle exec lefthook install +bundle exec rake +``` + +The authenticated smoke test is separate because it invokes the real Codex CLI +and consumes subscription allowance: + +```bash +bundle exec rake codex:smoke +``` + +Run it inside an appropriate process and memory boundary when changing process +lifecycle, timeout, or shell configuration behavior. + +## Pull requests + +1. Create a branch; hooks reject direct commits to `main` and `master`. +2. Add focused tests for behavior changes. +3. Run `bundle exec rake` and any relevant live smoke coverage. +4. Use Conventional Commits, including a meaningful body for non-trivial work. +5. Update `README.md` and `CHANGELOG.md` when user-facing behavior changes. +6. Open a pull request against `main` and explain the behavior, risks, and + verification performed. + +Do not include generated gems from `pkg/`, credentials, Codex session data, or +unrelated formatting changes. + +## Releases + +Only maintainers publish releases. See [docs/releasing.md](docs/releasing.md) for +the controlled release procedure. diff --git a/README.md b/README.md index e51c972..0e18011 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # RubyLLM Codex provider +[![Ruby](https://github.com/ethos-link/ruby_llm-codex/actions/workflows/ruby.yml/badge.svg)](https://github.com/ethos-link/ruby_llm-codex/actions/workflows/ruby.yml) +[![Gem Version](https://badge.fury.io/rb/ruby_llm-codex.svg)](https://rubygems.org/gems/ruby_llm-codex) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + This small adapter lets RubyLLM invoke the official local Codex CLI as a provider. Codex reuses the ChatGPT login stored by `codex login`, so these runs consume your Codex subscription allowance rather than OpenAI API credits. @@ -31,26 +35,23 @@ codex login Check the model list in your installed Codex version before a large run. Model availability depends on the account and currently installed CLI. -Run the automated unit tests and the two-request live smoke task with: +## Installation -```bash -bundle exec rake test -bundle exec rake codex:smoke -``` +Add the gem to your application's `Gemfile`: -The smoke task verifies the installed CLI version, then performs one plain-text -completion and one structured-output completion through the real RubyLLM -provider. It consumes Codex subscription allowance and requires a completed -login. Set `CODEX_MODEL`, `CODEX_BIN`, or `CODEX_TIMEOUT` to override its model, -executable, or 300-second request timeout. +```ruby +gem "ruby_llm-codex", "~> 0.1" +``` -For local development, add this project to your application: +Then run `bundle install`. You can also install it directly: -```ruby -gem "ruby_llm-codex", path: "/path/to/ruby_llm-codex" +```bash +gem install ruby_llm-codex ``` -Then use it like any explicit RubyLLM provider: +## Usage + +Require the gem and use Codex as an explicit RubyLLM provider: ```ruby require "ruby_llm-codex" @@ -91,6 +92,10 @@ By default every request: This prevents local `AGENTS.md`, plugins, MCP servers, repository contents, and saved session history from quietly affecting a comparison. +## Configuration + +### Per request + To deliberately let Codex inspect a repository or use selected configuration: ```ruby @@ -106,6 +111,8 @@ chat.with_params( ) ``` +### Global + Global configuration is also available: ```ruby @@ -145,6 +152,18 @@ If you later need streaming, persistent threads, or high throughput, replace the process-per-request implementation with a long-running `codex app-server` client while keeping the same RubyLLM provider surface. +## Troubleshooting + +- **`codex` is not found:** install the Codex CLI, run `codex login`, or set + `RubyLLM.config.codex_cli_path` to its absolute path. +- **A request times out:** increase `codex.timeout` or `CODEX_TIMEOUT` for the + smoke task. Timed-out process groups are terminated automatically. +- **Codex consumes excessive memory:** use the current gem version. The provider + explicitly disables Codex shell snapshots, which are unnecessary for its + completion-only execution and previously caused runaway Bash processes. +- **Local instructions affect output:** keep `ignore_user_config: true` and do + not set a working directory when you need isolated comparisons. + ## Development ```bash @@ -155,6 +174,13 @@ bundle install bundle exec rake ``` +To test an unreleased checkout from another application, use a local path in +that application's `Gemfile`: + +```ruby +gem "ruby_llm-codex", path: "/path/to/ruby_llm-codex" +``` + The default Rake task runs the unit suite and Standard Ruby. CI runs the same gate on Ruby 3.1.3, 3.4, and 4.0.3, then validates commit messages and git-cliff changelog generation. @@ -184,10 +210,10 @@ bundle exec lefthook install ## Release -Releases are tag-driven. Local release commands prepare the changelog, version -commit, and tag; GitHub Actions runs the full test matrix, publishes through -RubyGems trusted publishing, and creates the GitHub release from -`CHANGELOG.md`. +Releases are tag-driven. GitHub Actions runs the full test matrix, publishes +through RubyGems trusted publishing, and creates the GitHub release from +`CHANGELOG.md`. See [docs/releasing.md](docs/releasing.md) for repository setup, +the first-release procedure, verification, and recovery guidance. Install [git-cliff](https://git-cliff.org/) locally, check out a clean `main`, and run one of: @@ -199,22 +225,21 @@ bundle exec rake 'release:prepare[major]' bundle exec rake 'release:prepare[0.2.0]' ``` -The task: +For releases after `0.1.0`, the task: 1. Prepends the next changelog section from Conventional Commits. 2. Updates `lib/ruby_llm/codex/version.rb`. 3. Commits the release files and creates `vX.Y.Z`. 4. Pushes `main` and the tag to `origin`. -Before the first automated release, configure the gem's RubyGems trusted -publisher with owner `ethos-link`, repository `ruby_llm-codex`, workflow -`release.yml`, and environment `release`. The environment name must match the -protected GitHub environment used by the release job. +The initial `0.1.0` release only needs its existing version commit tagged after +the GitHub environment and pending RubyGems trusted publisher are configured. ## Contributing -Create a non-main branch, keep commits scoped and conventional, run -`bundle exec rake`, and open a pull request against `main`. +See [CONTRIBUTING.md](CONTRIBUTING.md). By participating, you agree to follow +the [Code of Conduct](CODE_OF_CONDUCT.md). Security reports should follow +[SECURITY.md](SECURITY.md), not a public issue. ## License diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..b9ac09d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,34 @@ +# Security policy + +## Supported versions + +Security fixes are provided for the latest released version. Because the gem is +pre-1.0, upgrades may include small compatibility changes documented in the +changelog. + +## Reporting a vulnerability + +Do not open a public issue for a suspected vulnerability. Use GitHub's private +vulnerability reporting for this repository. If that is unavailable, email +`devel@ethos-link.com` with: + +- the affected version and platform; +- a minimal reproduction or proof of concept; +- the expected security impact; +- any suggested mitigation; and +- whether the issue is already public. + +You should receive an acknowledgement within five business days. We will +coordinate validation, remediation, and disclosure with the reporter. + +## Security boundaries + +This gem starts the locally installed Codex CLI and reuses its existing ChatGPT +authentication. It does not collect, proxy, or store credentials. By default it +runs Codex in a fresh temporary directory, disables interactive approvals and +shell snapshots, uses a read-only sandbox, and does not inherit the parent +process environment for model-generated shell commands. + +Applications that override the working directory, sandbox, user configuration, +or environment inheritance assume responsibility for the additional access +granted to Codex. diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..4846c19 --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,79 @@ +# Releasing ruby_llm-codex + +Releases are immutable, tag-driven, and published by GitHub Actions through +RubyGems trusted publishing. Maintainers do not need a RubyGems API key. + +## One-time repository setup + +1. Push `main` to `git@github.com:ethos-link/ruby_llm-codex.git`. +2. In GitHub, create an environment named `release`. Add required reviewers if + the organization requires a manual publication gate. +3. Protect `main`, require pull requests, and require the Ruby, Commitlint, and + Changelog checks before merging. +4. In the RubyGems account that will own the gem, create a + [pending trusted publisher](https://rubygems.org/profile/oidc/pending_trusted_publishers) + with these exact values: + + | Field | Value | + | --- | --- | + | Gem name | `ruby_llm-codex` | + | GitHub owner | `ethos-link` | + | Repository | `ruby_llm-codex` | + | Workflow | `release.yml` | + | Environment | `release` | + +The workflow grants `id-token: write` only to the release job. RubyGems exchanges +that GitHub OIDC identity for short-lived credentials during publication. + +## Publish 0.1.0 + +The initial version and changelog are already committed. After the one-time +setup and a successful CI run on `main`, create and push its annotated tag: + +```bash +git tag -a v0.1.0 -m "Release v0.1.0" +git push origin v0.1.0 +``` + +The tag starts the Release workflow. The regular release task below handles +every subsequent version. + +## Later releases + +Install [git-cliff](https://git-cliff.org/), start from a clean and current +`main`, and choose the intended version increment: + +```bash +git switch main +git pull --ff-only +bundle exec rake 'release:prepare[patch]' +``` + +Use `minor`, `major`, or an explicit version such as `0.2.0` when appropriate. +The task updates the changelog and version constant, creates the release commit +and annotated tag, and pushes both. + +## Verify a release + +The Release workflow must complete all of the following: + +1. Pass the supported-Ruby test and style matrix. +2. Confirm that the tag matches `RubyLLM::Codex::VERSION`. +3. Find a matching `CHANGELOG.md` section. +4. Build and push the gem to RubyGems. +5. Create the GitHub release from the changelog entry. + +Afterward, verify the version on +[RubyGems](https://rubygems.org/gems/ruby_llm-codex) and install it in a clean +environment before announcing the release. + +## Failure handling + +- If CI fails before publication, fix the failure on a branch. Delete and + recreate the tag only if RubyGems does not contain that version. +- If RubyGems contains the version, never overwrite or reuse it. Fix forward + with a new patch release. +- If gem publication succeeds but GitHub release creation fails, create the + GitHub release for the existing tag using the matching changelog section. +- Never commit a RubyGems API key or add one as a repository secret for this + workflow. diff --git a/ruby_llm-codex.gemspec b/ruby_llm-codex.gemspec index 629f0ab..1618647 100644 --- a/ruby_llm-codex.gemspec +++ b/ruby_llm-codex.gemspec @@ -13,7 +13,7 @@ Gem::Specification.new do |spec| official Codex CLI, reuses local ChatGPT authentication, and maps RubyLLM structured-output schemas to Codex output schemas. TEXT - spec.homepage = "https://www.ethos-link.com/opensource/ruby_llm-codex" + spec.homepage = "https://github.com/ethos-link/ruby_llm-codex" spec.license = "MIT" spec.required_ruby_version = ">= 3.1.3" From a030951ee26e2bcb4b823b66da83d4a6c3d0951a Mon Sep 17 00:00:00 2001 From: Paulo Fidalgo Date: Fri, 17 Jul 2026 11:18:15 +0100 Subject: [PATCH 2/2] fix(ci): require Ruby 3.3 or newer Align the supported Ruby floor with the existing locked dependencies, including parallel 2.x, and replace the failing Ruby 3.1.3 matrix entry with Ruby 3.3. Update package metadata, documentation, Standard's syntax target, and the initial changelog so consumers and automation share the same compatibility contract. --- .github/workflows/ruby.yml | 2 +- .standard.yml | 2 +- CHANGELOG.md | 2 ++ README.md | 4 ++-- ruby_llm-codex.gemspec | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index f426bd9..7d263b8 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ["3.1.3", "3.4", "4.0.3"] + ruby-version: ["3.3", "3.4", "4.0.3"] steps: - uses: actions/checkout@v5 diff --git a/.standard.yml b/.standard.yml index 72b2693..49bff5f 100644 --- a/.standard.yml +++ b/.standard.yml @@ -1 +1 @@ -ruby_version: 3.1 +ruby_version: 3.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b4d7ab..e77ea9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,3 +22,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Disable unnecessary Codex shell snapshots to prevent Bash process explosions during completion-only runs. +- Align the documented Ruby requirement, CI matrix, syntax target, and locked + development dependencies on Ruby 3.3 or newer. diff --git a/README.md b/README.md index 0e18011..5a7ce0e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ mapping but not an identical wire-level experiment. ## Requirements -- Ruby 3.1.3 or newer +- Ruby 3.3 or newer - RubyLLM 1.16.0 or newer, below 2.0 - Codex CLI 0.144.5 or newer, available as `codex` - Linux or macOS (timeout cleanup relies on POSIX process groups) @@ -182,7 +182,7 @@ gem "ruby_llm-codex", path: "/path/to/ruby_llm-codex" ``` The default Rake task runs the unit suite and Standard Ruby. CI runs the same -gate on Ruby 3.1.3, 3.4, and 4.0.3, then validates commit messages and +gate on Ruby 3.3, 3.4, and 4.0.3, then validates commit messages and git-cliff changelog generation. The authenticated smoke task is intentionally separate because it consumes diff --git a/ruby_llm-codex.gemspec b/ruby_llm-codex.gemspec index 1618647..5ce915e 100644 --- a/ruby_llm-codex.gemspec +++ b/ruby_llm-codex.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |spec| TEXT spec.homepage = "https://github.com/ethos-link/ruby_llm-codex" spec.license = "MIT" - spec.required_ruby_version = ">= 3.1.3" + spec.required_ruby_version = ">= 3.3.0" repo = "https://github.com/ethos-link/ruby_llm-codex" branch = "main"