Skip to content

Latest commit

 

History

History
516 lines (377 loc) · 23.3 KB

File metadata and controls

516 lines (377 loc) · 23.3 KB

Contributing

We welcome your contributions to this project!

Please read the OpenTelemetry Contributor Guide for general information on how to contribute including signing the Contributor License Agreement, the Code of Conduct, and Community Expectations.

Before you begin

Specifications / Guidelines

As with other OpenTelemetry clients, opentelemetry-ruby follows the opentelemetry-specification and the library guidelines.

Focus on Capabilities, Not Structure Compliance

OpenTelemetry is an evolving specification, one where the desires and use cases are clear, but the method to satisfy those use cases are not.

As such, Contributions should provide functionality and behavior that conforms to the specification, but the interface and structure are flexible.

It is preferable to have contributions follow the idioms of the language rather than conform to specific API names or argument patterns in the spec.

For a deeper discussion, see: open-telemetry/opentelemetry-specification#165

Getting started

Everyone is welcome to contribute code via GitHub Pull Requests (PRs).

Fork the repo

Fork the project on GitHub by clicking the Fork button at the top of the repository and clone your fork locally:

git clone git@github.com:YOUR_GITHUB_NAME/opentelemetry-ruby-contrib.git

or

git clone https://github.com/YOUR_GITHUB_NAME/opentelemetry-ruby-contrib.git

It can be helpful to add the open-telemetry/opentelemetry-ruby-contrib repo as a remote so you can track changes (we're adding as upstream here):

git remote add upstream git@github.com:open-telemetry/opentelemetry-ruby-contrib.git

or

git remote add upstream https://github.com/open-telemetry/opentelemetry-ruby-contrib.git

For more detailed information on this workflow read the GitHub Workflow.

Run the tests

Setting up a running Ruby environment is outside the scope of this document.

This repository contains multiple Ruby gems:

  • Various instrumentation gems located in subdirectories of instrumentation
  • Various resource detector gems located in subdirectories of resources
  • Various propagation gems located in the subdirectories of propagator
  • opentelemetry-sampler-xray located in the sampler/xray directory

Each of these gems has its configuration and tests.

For example, to test opentelemetry-instrumentation-action_pack you would:

  1. Change directory to instrumentation/action_pack
  2. Install the bundle with bundle install
  3. Run the tests with bundle exec rake

Note: Some test suites make use of Appraisal, a library for testing against different versions of dependencies. To run tests in suites that use Appraisal:

  1. Change directory to the instrumentation you'd like to test, ex: instrumentation/action_pack
  2. Install the bundle with bundle exec appraisal install
  3. Run the tests with bundle exec appraisal rake test

Docker setup

We use Docker Compose to configure and build services used in development and testing. This makes it easier to test against libraries that have dependencies, such as the MySQL instrumentation gem. See docker-compose.yml for specific configuration details.

The services provided include:

  • app - main container environment scoped to the /app directory. Used primarily to build and tag the opentelemetry/opentelemetry-ruby-contrib:latest image.
  • x-instrumentation-<library_name> - container environment scoped to a specific instrumentation library. See docker-compose.yml for available services.

To test using Docker:

  1. Install Docker and Docker Compose for your operating system
  2. Get the latest code for the project
  3. Build the opentelemetry/opentelemetry-ruby-contrib image
    • docker-compose build
    • This makes the image available locally
  4. Install dependencies for the service you want to interact with
    • docker-compose run <service-name> bundle install
  5. Run the tests
    • docker-compose run <service-name> bundle exec rake test

Processing and visualizing traces locally

You may wish to test your changes against an OpenTelemetry collector. To facilitate this, we provide configuration in docker-compose.yml that should be sufficient.

By default, docker-compose launches all services, including the collector - docker-compose up from the repository root is sufficient. However, if you only wish to launch the collector, run docker-compose up jaeger otelcol instead.

The collector listens on the default HTTP and GRPC ports (4318 and 4317, respectively). You can visualize the traces from your work via the Jaeger trace UI by visiting localhost:16686 in your browser.

Make your modifications

Some important tips to keep in mind when making your modifications.

Always work in a branch from your fork

git checkout -b my-feature-branch

Do not open a pull request from your own main branch, because we squash when merging, and that will cause you problems when you update your fork after merging.

Use conventional commit messages

All commits to the main repository should follow the conventional commit standard. In a nutshell, this means commit messages should begin with a semantic tag such as feat:, fix:, docs:, test:, refactor:, etc... Our release tooling uses these tags to determine the semantics of your commit, such as how it affects semantic versioning of the libraries, and to generate changelogs from commit descriptions. If you are not familiar with conventional commits, please review the specification. It is pretty simple.

If you open a pull request without a conventional commit message, your reviewer may ask you to amend the commit message.

Documentation and style

We use a combinations of tool to check style rules, linting, links and spelling of the files within this repo. To run these checks, please run:

bundle install
npm ci

to ensure that the tools are installed.

And prior to submitting a pr run the following to perform all the checks:

npm run check
bundle exec rake rubocop

which will help to ensure your code complies and it passes all the test required of a pull request.

We also use Yard to generate class documentation automatically. Among other things, this means:

  • Methods and arguments should include the appropriate type annotations
  • You can use markdown formatting in your documentation comments

You can generate the docs locally to see the results, by running:

bundle install
bundle exec rake yard

Instrumentation author's guide

Please make sure that you review the Instrumentation author's guide before submitting a new instrumentation.

Create a pull request

You'll need to create a Pull Request once you've finished your work. The Kubernetes GitHub Workflow document has a significant section on PRs.

Open the PR against the open-telemetry/opentelemetry-ruby-contrib repository.

Please put [WIP] in the title, or create it as a Draft PR if the PR is not ready for review.

Create one pull request per change

An important implication of conventional commits is that each commit message can describe at most one change. For example, if you add a feature and fix a bug, the commit message cannot include both the feat: and fix: semantic tags, so you should split your change into multiple commits.

The same goes for pull requests. When we merge pull requests, we generally do so by squashing, so your pull request will result in a single commit in the repository, and in turn will correspond to exactly one entry in the changelog. Therefore, please scope each pull request to include a single change.

Sign the Contributor License Agreement (CLA)

All PRs are automatically checked for a signed CLA. Your first PR fails this check if you haven't signed the CNCF CLA.

The failed check displays a link to details which walks you through the process. Don't worry it's painless!

Review and feedback

PRs require a review from one or more of the code owners before merge. You'll probably get some feedback from these fine folks which helps to make the project that much better. Respond to the feedback and work with your reviewer(s) to resolve any issues.

Some of the things the code owners are looking for include:

Reviewers are responsible for ensuring that each merged PR's commit message conforms to conventional commits. This may mean editing the commit message or the pull request title when you merge the pull request. Alternately, the reviewer may ask the pull request submitter to amend the commit message of their initial commit.

In addition, when a change is complex or a reviewer is unfamiliar with the code, the reviewer may seek additional reviews from people more familiar with the change before merging a PR.

Component Ownership

This repository contains many components which are maintained by more than the typical set of ruby-contrib maintainers and approvers. Each component in this repository SHOULD have a component owner who is responsible for maintaining it. The README.md for each component SHOULD contain its owner, but the source of truth for component ownership is in .github/component_owners.yml.

Component owners are generally given authority to make decisions relating to implementation and feature requests for their components, provided they follow the best practices set out by the maintainers and the mission, vision and values of the OpenTelemetry Project. To facilitate independent triage of issues pertaining to the owned component, component owners are assigned the Triager role.

Component owners MUST do their best to maintain a high level of quality, security, performance, and specification compliance within their components. Maintainers may override the decisions of component owners, but should only do so when they feel one or more of these traits is compromised.

Becoming a Component Owner

To become a component owner, contributors MUST be a member of the OpenTelemetry GitHub organization. To become a member, follow the steps in the community guidelines for membership requirements.

To become a component owner, contributors SHOULD demonstrate prior knowledge of the instrumented package or the concepts therein.

Ways do to so may be by providing proof of:

  • current or prior involvement with the community that develops the upstream package
    • Example: A person working on MongoDB requesting ownership over a MongoDB instrumentation
  • current or prior involvement with a community that develops systems with similar concepts
    • Example: A person previously working on MySQL requesting ownership of a instrumentation package that instruments another database client library instrumentation.
  • current or prior extensive use of the instrumented package in other project they are involved in
    • Example: A person working at a company that makes extensive use of the koala library requesting ownership of the opentelemetry-instrumentation-koala package.
  • a vested interest in the telemetry being emitted from that instrumentation
    • Example: A person employed at an observability vendor that relies on the continued maintenance of the instrumentation

Examples of proof may include but are not limited to:

  • Links to issues/PRs they worked on
  • Links to blog posts authored by them on behalf of the organization developing that system
  • Membership in GitHub teams/organizations that are associated with the development of the upstream package

Aspiring Component Owners MUST agree to uphold the mission, vision and values of the OpenTelemetry project. Further, aspiring component owners are expected to have knowledge of the OpenTelemetry Semantic Conventions and MUST agree to adhere to the rules set out therein.

If all these conditions are met, aspiring component owners are encouraged to self-nominate by opening an issue. @open-telemetry/ruby-contrib-maintainers will then engage on the issue, may ask questions, and will then - based on the information provided on the issue - either approve or deny the ownership request. If the ownership request has been approved, the new component owner opens a PR to add themselves to the list of owners (.github/component_owners.yml) for that package. @open-telemetry/ruby-contrib-maintainers will add the component owner to @open-telemetry/ruby-contrib-triagers.

Releases

This repository includes a set of tools for releasing gems. Only maintainers can perform releases.

Normal release process

Releases are normally performed using GitHub Actions.

  1. Wait for the CI checks on the latest main branch commit to succeed. The release scripts will not run unless the build is green.
  2. In the GitHub UI, go to the Actions tab, select the Open release request workflow, and run the workflow manually using the dropdown in the upper right.
    • Releases must be run from the main branch.
    • If you leave the Gems to release field blank, the script will find all the gems that have had conventional-commit-tagged changes since their last release. Alternately, you can specify which gems to release by including their names, space-delimited, in this field. You can optionally append :<version> to any gem in the list to specify the version to release, or omit the version to let the script decide based on conventional commits. You can also use the special name all to force release of all gems (and even all:<version> to release all gems with the same version.)
  3. The workflow will analyze the conventional commit messages for the gems to release, and will open a release pull request. This pull request will include the appropriate changes to each gem's version constants, and an initial changelog entry for each gem. Note that it is possible to release more than one gem using a single release pull request.
  4. You may optionally make further modifications to the pull request branch. For example, the workflow will suggest a version number based on semver analysis of the conventional commit types, but you can choose to release a different version. You might also want to edit the changelog wording.
  5. To trigger the release(s), merge the release pull request. Note that the label release: pending will have been applied to the pull request when it was opened; make sure the label is still there when you merge it.
  6. The automated release script will run automatically, and will release the gem(s) once CI has completed. This includes:
    • For each gem, it will create a release tag and a GitHub release.
    • It will build and push the gems to rubygems.
    • If the releases succeed, the script will update the release pull request with the results and change its label to release: complete. If something went wrong, the script will, if possible, report the error on the release pull request and change its label to release: error. It will also attempt to open an issue to alert you to the failure.
  7. If you change your mind and do not want to follow through on a release pull request, just close it without merging. (The release scripts will then automatically change its label to release: aborted for you.)

Release troubleshooting

If a release fails, the release scripts will attempt to alert you by opening an issue and/or updating the release pull request. However, you may also need to review the release logs for the GitHub Actions workflows.

About the release workflows

There are four GitHub actions workflows related to releases.

  • Open release request is the main release entrypoint, and is used to open a release pull request. If something goes wrong with this process, the logs will appear in the workflow run.
  • Force release is generally used only to restart a failed release.
  • [release hook] Update open releases is run on pushes to the main branch, and pushes warnings to open release pull requests if you make modifications before triggering the release (i.e. because you might need to update the changelogs.)
  • [release hook] Process release is the main release automation script and is run when a pull request is closed. If it determines that a release pull request was merged, it kicks off the release process for the affected gems. It also updates the label on a closed release pull request. Finally, it deletes release branches when they are no longer being used. If something goes wrong with any of these processes, the logs will appear here.

Restarting a release

If you've already merged a release pull request and want to retry a failed release, you can use the Force release workflow.

  1. If the release tag has already been created, delete it manually using the GitHub UI.
  2. In the GitHub UI, go to the Actions tab, select the Force release workflow, and run it manually.
    • You must provide the gem name and version explicitly in the fields.
    • The Extra flags field is useful for advanced cases. For example, if the GitHub release tag is already created and the gem already pushed to Rubygems, but the docs still need to be built, you can pass --only=docs to perform only that one step. You can also force a release even if the build is not green or the version/changelog checks are failing, by passing --skip-checks. For more details, install the toys gem and run toys release perform --help locally.

Running releases locally

It is possible to run the release scripts locally if GitHub Actions is having problems. You will need to install the toys gem first, and you will need the Rubygems API key for opentelemetry-ruby-contrib. These commands will succeed only if you have write access to the repository.

To open a release pull request:

toys release request

Pass the --gems= flag to provide a list of gems, or omit it to release all changed gems.

To force-release, assuming the version and changelog are already modified:

toys release perform --rubygems-api-key=$API_KEY $GEM_NAME $GEM_VERSION

Pass --help to either command for details on the options.

Adding gems

The release configuration is defined in the .toys/.data/releases.yml file. Gems must be listed in this file to be supported by the release process.

To add a gem, add an appropriate entry under the gems: section. The name: and directory: fields are generally required, as is version_constant:. Some gems will also need to provide version_rb_path: if the file path does not correspond exactly to the gem name.

For releases to succeed, new gems MUST include the following:

  • The above configuration entry.
  • The *.gemspec file, with the name matching the gem name.
  • A version.rb file in the standard location, or in a location listed in the configuration.
  • A CHANGELOG.md file.
  • A yard rake task.

Dependabot updates

Note

This repository is in the process of migrating to Renovate.

This repository uses Dependabot to keep dependencies up to date, however there shared development dependencies are often scattered across multiple gems. Dependabot does not currently support the ability to group dependencies for gems in multiple subdirectories, so we use a custom script to bulk update dependencies across all gems.

Note: This script uses a version of sed that isn't available on MacOS bash. You'll need to use an ubuntu-linux machine to execute it. One way to accomplish this is to run docker-compose run app and execute the script within the container.

E.g. if you want to update Rubocop to version 1.56.1, you would run:

$> bin/update-dependencies rubocop 1.56.1

Review your changes and commit
Press any key to continue

This will then run a bulk update on all of the gems in the repository, and then prompt you to review the changes and stage them for a commit:

diff --git a/propagator/ottrace/Gemfile b/propagator/ottrace/Gemfile
index 42c5ecba..74fcc743 100644
--- a/propagator/ottrace/Gemfile
+++ b/propagator/ottrace/opentelemetry-propagator-ottrace.gemspec
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
   gem 'minitest', '~> 5.0'
   gem 'rake', '~> 13.0'
-  gem 'rubocop', '~> 1.50.0'
+  gem 'rubocop', '~> 1.56.1'
   gem 'simplecov', '~> 0.22.0'
   gem 'yard', '~> 0.9'
   gem 'yard-doctest', '~> 0.1.6'
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y

diff --git a/propagator/xray/Gemfile b/propagator/xray/Gemfile
index e29acbfc..85622d25 100644
--- a/propagator/xray/Gemfile
+++ b/propagator/xray/Gemfile
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
   gem 'minitest', '~> 5.0'
   gem 'rake', '~> 13.0'
-  gem 'rubocop', '~> 1.50.0'
+  gem 'rubocop', '~> 1.56.1'
   gem 'simplecov', '~> 0.22.0'
   gem 'yard', '~> 0.9'
   gem 'yard-doctest', '~> 0.1.6'
(1/1) Stage this hunk [y,n,q,a,d,e,?]? y

Updating Ruby version requirements

To update the minimum Ruby version requirement across all gems in the repository, use the bin/update-ruby-version script:

# Update to Ruby 3.3 minimum
bin/update-ruby-version 3.3

# Supports patch versions and pre-releases
bin/update-ruby-version 3.2.0
bin/update-ruby-version 3.4.0.alpha

The script will:

  1. Validate the version format
  2. Update spec.required_ruby_version in all gemspec files
  3. Show a summary of changes

After running the script:

  1. Review changes with git diff
  2. Test against the new minimum Ruby version
  3. Update CI configurations in .github/workflows
  4. Update .rubocop.yml to set the TargetRubyVersion
  5. Remove any conditional logic handling Ruby versions in Appraisal files that are no longer needed
  6. Remove any conditional logic in test cases that are no longer needed
  7. Commit with a message like chore: update minimum Ruby version to 3.3