Skip to content

Publish Ruby observability plugin gem#413

Draft
ccschmitz-launchdarkly wants to merge 1 commit intomainfrom
O11Y-1150-publish-ruby-observability-gem
Draft

Publish Ruby observability plugin gem#413
ccschmitz-launchdarkly wants to merge 1 commit 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 8 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 8 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 8 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

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@b8b614efb63de96a885da6d588f7ca1205f8e6e4 # v1.174.0
View step-by-step instructions
  1. Find the action reference uses: ruby/setup-ruby@v1.
  2. Replace @v1 with the full commit SHA for the specific version you want to use, for example: uses: ruby/setup-ruby@b8b614efb63de96a885da6d588f7ca1205f8e6e4 # v1.174.0 (find the latest SHA at https://github.com/ruby/setup-ruby/releases).
  3. Repeat this change for any other instance of ruby/setup-ruby@v1 in your GitHub Actions workflows.

Pinning the action to a commit SHA protects your workflow against unexpected changes or tampering in the action 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.

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@6938946b8d0615c273941a9d771a290edbe0727b # v1
View step-by-step instructions
  1. Visit the ruby/setup-ruby GitHub Actions repository at https://github.com/ruby/setup-ruby/releases or https://github.com/ruby/setup-ruby/tags.
  2. Find the commit SHA for the specific version you want to use (for example, v1). Click the tag and copy the full 40-character commit SHA.
  3. Replace ruby/setup-ruby@v1 with ruby/setup-ruby@<full-commit-sha> # v1 wherever it appears in your workflow file. For example: uses: ruby/setup-ruby@6938946b8d0615c273941a9d771a290edbe0727b # v1
  4. Repeat this replacement for all uses of ruby/setup-ruby in your workflow file.

Pinning actions to a full commit SHA prevents supply chain attacks if a malicious update is introduced to the action’s code after your workflow is set up.

💬 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
uses: ruby/setup-ruby@e81d9b575145cb9c55e634a5caa9083a869c387a # v1.171.0
View step-by-step instructions
  1. Find all uses of ruby/setup-ruby@v1 in your workflow YAML file.
  2. Replace @v1 with a full length commit SHA that corresponds to the release you want to use. For example: uses: ruby/setup-ruby@e81d9b575145cb9c55e634a5caa9083a869c387a # v1.171.0
  3. You can look up the latest or specific SHA on the ruby/setup-ruby GitHub releases or tags page: https://github.com/ruby/setup-ruby/tags
  4. Keep the version comment (like # v1.171.0) for easier tracking, but always use the commit SHA for pinning.
    Using a full length commit SHA ensures that the workflow always uses the exact same code 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.

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

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

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: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0
# Pinned to release-secrets-v1.2.0 commit SHA to ensure immutability and security.
uses: launchdarkly/gh-actions/actions/release-secrets@3652a20f1d9b66fa2d04b00a218b5aa99c1a86b8 # release-secrets-v1.2.0
View step-by-step instructions
  1. Replace the version tag in the uses: launchdarkly/gh-actions/actions/release-secrets@release-secrets-v1.2.0 line with a full commit SHA from the referenced action's repository.
  2. Find the commit SHA that matches the release-secrets-v1.2.0 release in the launchdarkly/gh-actions repository. You can find this SHA on GitHub by navigating to the tag and viewing its commit.
  3. Update the line to: uses: launchdarkly/gh-actions/actions/release-secrets@<commit-sha> # release-secrets-v1.2.0 (replace <commit-sha> with the actual SHA you found).

Pinning actions in this way prevents unexpected changes in third-party actions, even if the tag is moved or replaced.

💬 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@d1dbd87d63070f974d3835ac0aac6bf747752d7d # v1
View step-by-step instructions
  1. Replace ruby/setup-ruby@v1 with a reference to a specific full-length commit SHA for the ruby/setup-ruby action.
  2. Visit https://github.com/ruby/setup-ruby/tags to find the latest release, then click on the tag to get the full commit SHA (it will look like a 40-character hexadecimal string).
  3. Update the uses line to: uses: ruby/setup-ruby@<commit-sha> # v1 where <commit-sha> is replaced with the actual commit SHA you found.
    For example: uses: ruby/setup-ruby@a1b2c3d4e5f678901234567890abcdef12345678 # v1

Pinning to a specific commit SHA ensures that your workflow always uses the same trusted code and cannot be silently changed upstream.

💬 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