Skip to content

Publish Ruby observability plugin gem#413

Draft
ccschmitz-launchdarkly wants to merge 2 commits intomainfrom
O11Y-1150-publish-ruby-observability-gem
Draft

Publish Ruby observability plugin gem#413
ccschmitz-launchdarkly wants to merge 2 commits intomainfrom
O11Y-1150-publish-ruby-observability-gem

Conversation

@ccschmitz-launchdarkly
Copy link
Contributor

@ccschmitz-launchdarkly ccschmitz-launchdarkly commented Mar 4, 2026

Summary

Adds the full CI and release pipeline for the launchdarkly-observability Ruby gem (sdk/@launchdarkly/observability-ruby), bringing it in line with the existing Python, .NET, and Android plugin publish workflows.

  • Release Please integration: Registers the Ruby package in release-please-config.json and .release-please-manifest.json so version bumps and changelogs are automated. Adds a x-release-please-version marker to version.rb.
  • Publish action & release workflows: Creates a reusable .github/actions/publish-ruby-sdk/ composite action (gem build, SLSA provenance hashing, gem push via AWS SSM-managed RubyGems key). Wires it into both release-please.yml (automated releases) and manual-publish.yml (manual trigger).
  • CI workflow: Adds .github/workflows/ruby-plugin.yml with quality checks (tests + RuboCop on Ruby 3.1 and 3.3) and E2E tests against the Rails demo and API-only example apps.
  • README: Lists the Ruby gem in the packages table with RubyGems and CI badges.

Relates to O11Y-1150.

How did you test this change?

  • Verified YAML syntax of all new and modified workflow files
  • Confirmed the release-please config and manifest JSON are valid
  • CI workflow structure follows the same patterns as python-plugin.yml and the existing ruby.yml (highlight-ruby)

Are there any deployment considerations?

  • The SSM parameter /production/common/releasing/rubygems/token must be provisioned in AWS before the first publish. Alternatively, the existing RUBYGEMS_API_KEY repo secret (used by highlight-ruby) can be used if the action is updated to reference it directly.
  • The gem name launchdarkly-observability must be claimed on rubygems.org under the LD org before the first release.

Comment on lines +15 to +42
name: Quality Check
runs-on: ubuntu-22.04-8core-32gb
strategy:
matrix:
ruby: ['3.1', '3.3']
defaults:
run:
working-directory: ./sdk/@launchdarkly/observability-ruby
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
working-directory: ./sdk/@launchdarkly/observability-ruby
- name: Install dependencies
run: bundle install
- name: Test
run: bundle exec rake test
- name: Rubocop
run: bundle exec rubocop
- name: Build gem
run: gem build *.gemspec

e2e-rails:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 21 days ago

In general, to fix this issue you add a permissions: block either at the top level of the workflow (affecting all jobs that don’t override it) or per-job, and set it to the least privileges required. For a CI workflow that just checks out code and runs tests, contents: read is typically sufficient; additional scopes (like pull-requests: write) are only needed if the workflow posts statuses/comments or modifies GitHub resources.

For this specific workflow, none of the build, e2e-rails, or e2e-rails-api-only jobs perform write operations via the GitHub API; they only read the repository, install gems, run tests, lint, and build a gem locally. Therefore, we can safely define a single root-level permissions block that applies to all jobs. The best minimal fix is to insert:

permissions:
    contents: read

after the on: block and before concurrency:. This keeps existing behavior unchanged while explicitly constraining GITHUB_TOKEN to read-only repository contents.

No new imports, methods, or definitions are required; this is a pure workflow configuration change within .github/workflows/ruby-plugin.yml.

Suggested changeset 1
.github/workflows/ruby-plugin.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ruby-plugin.yml b/.github/workflows/ruby-plugin.yml
--- a/.github/workflows/ruby-plugin.yml
+++ b/.github/workflows/ruby-plugin.yml
@@ -9,6 +9,9 @@
             - 'sdk/@launchdarkly/observability-ruby/**'
             - '.github/workflows/ruby-plugin.yml'
 
+permissions:
+    contents: read
+
 concurrency: ${{ github.workflow }}-${{ github.ref }}
 jobs:
     build:
EOF
@@ -9,6 +9,9 @@
- 'sdk/@launchdarkly/observability-ruby/**'
- '.github/workflows/ruby-plugin.yml'

permissions:
contents: read

concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
build:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +43 to +65
name: Rails E2E Tests
runs-on: ubuntu-22.04-8core-32gb
defaults:
run:
working-directory: ./e2e/ruby/rails/demo
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
working-directory: ./e2e/ruby/rails/demo
- name: Install dependencies
run: bundle install
- name: Test
run: bundle exec rake
- name: Rubocop
run: bundle exec rubocop

e2e-rails-api-only:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 21 days ago

In general, to fix this issue you should explicitly define a permissions block either at the workflow root (so it applies to all jobs by default) or inside each job, and set it to the minimal required scope, typically contents: read for build/test workflows. This documents the intended access and prevents accidental elevation if repository/org defaults change.

For this specific workflow, none of the jobs (build, e2e-rails, e2e-rails-api-only) perform any write operation to the repository or other GitHub resources; they only need to read the repository contents via actions/checkout. The best minimal fix is to add a root-level permissions block right after the name: (or before on:) setting contents: read. This will apply to all jobs and keep the YAML simple.

Concretely, in .github/workflows/ruby-plugin.yml, insert:

permissions:
    contents: read

between the existing name: Ruby Observability Plugin line and the on: block. No additional imports or dependencies are needed, and no job-level changes are required because the root-level permissions cover all jobs that don’t override them.

Suggested changeset 1
.github/workflows/ruby-plugin.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ruby-plugin.yml b/.github/workflows/ruby-plugin.yml
--- a/.github/workflows/ruby-plugin.yml
+++ b/.github/workflows/ruby-plugin.yml
@@ -1,5 +1,8 @@
 name: Ruby Observability Plugin
 
+permissions:
+    contents: read
+
 on:
     push:
         branches: ['main']
EOF
@@ -1,5 +1,8 @@
name: Ruby Observability Plugin

permissions:
contents: read

on:
push:
branches: ['main']
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +66 to +84
name: Rails API-Only E2E Tests
runs-on: ubuntu-22.04-8core-32gb
defaults:
run:
working-directory: ./e2e/ruby/rails/api-only
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
working-directory: ./e2e/ruby/rails/api-only
- name: Install dependencies
run: bundle install
- name: Test
run: bundle exec rake

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 21 days ago

In general, fix this by adding an explicit permissions block that limits GITHUB_TOKEN to only the scopes needed. Here, all three jobs (build, e2e-rails, e2e-rails-api-only) only read repository contents via actions/checkout and then run local commands, so contents: read at the workflow level is sufficient and preserves existing behavior.

The best single change, without altering functionality, is to add a root-level permissions: block (applies to all jobs lacking their own permissions blocks) right after the on: section. Specifically, in .github/workflows/ruby-plugin.yml, between lines 11 and 12, insert:

permissions:
    contents: read

This constrains the GITHUB_TOKEN used by actions/checkout@v4 and any other steps to read-only repository contents while keeping everything else intact. No imports, methods, or additional definitions are needed.

Suggested changeset 1
.github/workflows/ruby-plugin.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ruby-plugin.yml b/.github/workflows/ruby-plugin.yml
--- a/.github/workflows/ruby-plugin.yml
+++ b/.github/workflows/ruby-plugin.yml
@@ -9,6 +9,9 @@
             - 'sdk/@launchdarkly/observability-ruby/**'
             - '.github/workflows/ruby-plugin.yml'
 
+permissions:
+    contents: read
+
 concurrency: ${{ github.workflow }}-${{ github.ref }}
 jobs:
     build:
EOF
@@ -9,6 +9,9 @@
- 'sdk/@launchdarkly/observability-ruby/**'
- '.github/workflows/ruby-plugin.yml'

permissions:
contents: read

concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
build:
Copilot is powered by AI and may make mistakes. Always verify output.
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
Copy link

@semgrep-code-launchdarkly semgrep-code-launchdarkly bot Mar 4, 2026

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🥳 Removed in commit 95935a4 🥳

with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
Copy link

@semgrep-code-launchdarkly semgrep-code-launchdarkly bot Mar 4, 2026

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🚀 Removed in commit 95935a4 🚀

with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1
Copy link

@semgrep-code-launchdarkly semgrep-code-launchdarkly bot Mar 4, 2026

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🧹 Removed in commit 95935a4 🧹

working-directory: ${{ inputs.workspace-path }}

- name: Get RubyGems API key
uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
Copy link

@semgrep-code-launchdarkly semgrep-code-launchdarkly bot Mar 4, 2026

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🎈 Removed in commit 95935a4 🎈

uses: actions/checkout@v4

- name: Install Ruby
uses: ruby/setup-ruby@v1
Copy link

@semgrep-code-launchdarkly semgrep-code-launchdarkly bot Mar 4, 2026

Choose a reason for hiding this comment

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

An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

🍰 Removed in commit 95935a4 🍰

Fix the SSM parameter path for the RubyGems API key to match the
known-working path used by ruby-server-sdk (api_key not token), and
add SLSA provenance documentation for the Ruby gem.
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@4fd86e9f50af86b19ad0bb74fba32503353e8dd3 # pinned to commit SHA for security
View step-by-step instructions
  1. Replace uses: ruby/setup-ruby@v1 with a reference that pins the action to a specific full-length commit SHA. You can find the latest SHA for ruby/setup-ruby in the repository's GitHub Releases or by checking https://github.com/ruby/setup-ruby/tags.
  2. Update each occurrence, for example: uses: ruby/setup-ruby@<commit-SHA> where <commit-SHA> is the full 40-character SHA. For example: uses: ruby/setup-ruby@4fd86e9f50af86b19ad0bb74fba32503353e8dd3.
  3. Ensure the line does not use only a tag like @v1 or @v1.172.0, as tags can be changed or moved, while SHAs ensure immutability and prevent attackers from altering the workflow by changing action code.

Using a full commit SHA ensures the exact same version of the action is always used, protecting your workflows from unexpected changes or malicious updates.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.

You can view more details about this finding in the Semgrep AppSec Platform.

with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
uses: ruby/setup-ruby@v1
# Pinning to a specific commit SHA for security per Semgrep recommendation.
uses: ruby/setup-ruby@4f4918cfaa48f36f02ea025fa277dccb77b4c41d
View step-by-step instructions
  1. Visit the official ruby/setup-ruby GitHub action repository: https://github.com/ruby/setup-ruby/releases.
  2. Find the commit SHA for the version or release you want to use (for example, the latest v1 release). You can get this SHA from the "Commits" section or from the release tag details.
  3. Replace ruby/setup-ruby@v1 with the pinned format: ruby/setup-ruby@<FULL_SHA>, inserting the full commit SHA you obtained. For example: uses: ruby/setup-ruby@a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
  4. Make the same replacement for every instance of ruby/setup-ruby@v1 elsewhere in your workflow files.

By pinning to a specific commit SHA, you ensure the action can't be silently changed by the repository owner or a malicious actor.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.

You can view more details about this finding in the Semgrep AppSec Platform.

with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Ruby
uses: ruby/setup-ruby@v1

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
uses: ruby/setup-ruby@v1
# Pinned to specific commit SHA for setup-ruby v1. Update periodically for security & bugfixes.
uses: ruby/setup-ruby@a9d7722c7c55796164a6e5bcfbe5bfad4f5a017f
View step-by-step instructions
  1. Replace uses: ruby/setup-ruby@v1 with a specific commit SHA from the ruby/setup-ruby repository. For example: uses: ruby/setup-ruby@a9d7722c7c55796164a6e5bcfbe5bfad4f5a017f
  2. Obtain the latest commit SHA from the relevant release by visiting https://github.com/ruby/setup-ruby/tags or the GitHub repository's commits page.
  3. Update all instances of ruby/setup-ruby@v1 in your workflow files to use the full commit SHA.
    For example: uses: ruby/setup-ruby@a9d7722c7c55796164a6e5bcfbe5bfad4f5a017f
  4. Ensure you update the SHA periodically to keep receiving upstream updates and bug/security fixes.

Pinning to a full commit SHA ensures that your workflow always uses the expected version of the action and protects against supply chain attacks.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.

You can view more details about this finding in the Semgrep AppSec Platform.

uses: actions/checkout@v4

- name: Install Ruby
uses: ruby/setup-ruby@v1

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
An action sourced from a third-party repository on GitHub is not pinned to a full length commit SHA. Pinning an action to a full length commit SHA is currently the only way to use an action as an immutable release. Pinning to a particular SHA helps mitigate the risk of a bad actor adding a backdoor to the action's repository, as they would need to generate a SHA-1 collision for a valid Git object payload.

To resolve this comment:

✨ Commit Assistant fix suggestion

Suggested change
uses: ruby/setup-ruby@v1
uses: ruby/setup-ruby@5949c940b60e6b321d6e958dd42d9c7c1f72b08f # Pinned to latest stable SHA as recommended for security
View step-by-step instructions
  1. Replace uses: ruby/setup-ruby@v1 with a specific, full-length commit SHA from the ruby/setup-ruby repository.
    For example, change it to uses: ruby/setup-ruby@5949c940b60e6b321d6e958dd42d9c7c1f72b08f (get the most recent stable SHA from https://github.com/ruby/setup-ruby/tags or from their releases).
  2. Ensure the line now reads: uses: ruby/setup-ruby@<commit-sha>, replacing <commit-sha> with the actual full commit SHA.
    Pinning the action to a full commit SHA protects you from upstream changes or compromises in the repository.
💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by third-party-action-not-pinned-to-commit-sha.

You can view more details about this finding in the Semgrep AppSec Platform.

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