diff --git a/.github/actions/select_gem/action.yml b/.github/actions/select_gem/action.yml new file mode 100644 index 0000000000..861adfd34a --- /dev/null +++ b/.github/actions/select_gem/action.yml @@ -0,0 +1,59 @@ +name: Select Gems +description: Selects the Gems +inputs: + token: + description: Token used to add labels + required: false + type: string + default: + description: Gem string to be used if not able use pr label + required: false + type: string + default: "" +outputs: + gems: + description: The gems which have been changed + value: ${{steps.select.outputs.gems}} + +runs: + using: composite + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 + name: Calculate Gems + if: ${{ github.event_name == 'pull_request' }} + id: label + with: + repo-token: "${{ inputs.token }}" + sync-labels: true + + - name: Select Gems + id: select + shell: bash + run: | + # Select Gems + default="${{ inputs.default }}" + deny='["ci", "deprecated"]' + labels="${{ steps.label.outputs.all-labels || inputs.default }}" + # labels is a comma-separated string, convert to JSON array + json=$(printf '%s\n' "$labels" | jq -R 'split(",")') + + # Remove deny-listed items + filtered=$(echo "$json" | jq --argjson deny "$deny" '[ .[] | select(. as $l | $deny | index($l) | not) ]') + + # Guarantee valid JSON by adding default + if [ -z "$filtered" ] || [ "$filtered" = "null" ] || [ "$(echo "$filtered" | jq 'length')" -eq 0 ]; then + filtered=$(jq -n --arg d "$default" '[ $d ]') + fi + + { + echo "gems<> "$GITHUB_OUTPUT" + + - shell: bash + run: | + # Log Gems Selected + echo "Gems selected = ${{ steps.select.outputs.gems }}" diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 22dcd5424a..921c3f42b7 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -37,6 +37,7 @@ dependencyDashboardCategory: "Min Ruby Runtime", matchDepNames: ["ruby"], matchFileNames: [ + ".github/workflows/ci-build-ruby.yml", ".github/workflows/ci-markdown-checks.yml", "**/*.gemspec", ], diff --git a/.github/workflows/ci-build-ruby.yml b/.github/workflows/ci-build-ruby.yml new file mode 100644 index 0000000000..dc7fbb6b5a --- /dev/null +++ b/.github/workflows/ci-build-ruby.yml @@ -0,0 +1,143 @@ +name: Build / Ruby + +on: + workflow_dispatch: + push: + branches: + - main + paths: &path_filters + - ".yardopts" + - "GEMFILE" + - "RAKEFILE" + - "**/.yardopts" + - "**/GEMFILE" + - "**/LICENSE" + - "**/RAKEFILE" + - "**/*.gemspec" + - "**/*.md" + - "**/lib/**" + - ".github/actions/select_gem/action.yml" + - ".github/workflows/ci-buid-ruby.yml" + pull_request: + branches: + - main + paths: *path_filters + merge_group: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} # Ensure that only one instance of this workflow is running per event type and ref + cancel-in-progress: true # Cancel any previous runs of this workflow for the same event type and ref +jobs: + analyze: + if: ${{ github.repository == 'open-telemetry/opentelemetry-ruby-contrib' }} + runs-on: ubuntu-24.04 + outputs: + gems: ${{steps.select_gem.outputs.gems}} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: ./.github/actions/select_gem + name: Select Gems + id: select_gem + with: + token: "${{ secrets.GITHUB_TOKEN }}" + default: "Everything" + + build: + runs-on: ubuntu-24.04 + needs: analyze + if: ${{ github.repository == 'open-telemetry/opentelemetry-ruby-contrib' && needs.analyze.outputs.gems != '[]' }} + strategy: + matrix: + gem: ${{ fromJson(needs.analyze.outputs.gems) }} + fail-fast: false + name: ${{ matrix.gem }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Setup + if: ${{ matrix.gem != 'Everything' }} + id: setup + shell: bash + run: | + # đŸ› ī¸ Setup đŸ› ī¸ + dir=$(find . -iname 'opentelemetry-${{ matrix.gem }}.gemspec' -exec dirname {} \;) + echo "gem_dir=${dir}" >> $GITHUB_OUTPUT + - name: Install Ruby + uses: ruby/setup-ruby@e65c17d16e57e481586a6a5a0282698790062f92 # v1.300.0 + with: + ruby-version: "ruby-3.3.11" + - name: Compute Gemfile hash + id: lockhash + shell: bash + working-directory: ${{ steps.setup.outputs.gem_dir }} + run: | + files=$(find . -name "Gemfile" | sort) + if [[ -n "$files" ]]; then + hash=$(sha256sum $files | sha256sum | cut -d ' ' -f1) + echo "hash=$hash" >> $GITHUB_OUTPUT + else + echo "hash=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT + fi + - name: Cache Bundler + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4 + with: + path: | + vendor/bundle + .bundle + ${{ steps.setup.outputs.gem_dir }}/vendor/bundle + ${{ steps.setup.outputs.gem_dir }}/.bundle + key: bundler-${{ runner.os }}-${{ matrix.gem }}-${{ steps.lockhash.outputs.hash }} + restore-keys: | + bundler-${{ runner.os }}-${{ matrix.gem }}- + - name: Install Tools & Gem Deps + run: | + # Always install tools + bundle config set path vendor/bundle + bundle config set clean false + bundle install --jobs 4 --retry 3 + + # Conditionally install gem deps + if [ "${{ matrix.gem }}" == "Everything" ]; then + bundle exec rake install + fi + working-directory: "${{ steps.setup.outputs.gem_dir }}" + - name: YARD + shell: bash + run: | + # 📄 Yard Docs 📄 + bundle exec rake yard + working-directory: "${{ steps.setup.outputs.gem_dir }}" + - name: Build Gem + shell: bash + run: | + # đŸ“Ļ Build Gem đŸ“Ļ + bundle exec rake build + working-directory: "${{ steps.setup.outputs.gem_dir }}" + + verify: + runs-on: ubuntu-24.04 + needs: + - analyze + - build + if: ${{ github.repository == 'open-telemetry/opentelemetry-ruby-contrib' && always() }} # Always run so we can detect failures/skips + steps: + - name: Count builds + run: | + if [ "${{ needs.analyze.outputs.gems }}" = "[]" ]; then + echo "::error:: ❌ No gems selected — build matrix was empty." + exit 1 + fi + gems='${{ needs.analyze.outputs.gems }}' + count=$(echo "$gems" | jq 'length') + echo "â„šī¸ Build count: $count" + + - name: Check build results + run: | + if [ "${{ needs.build.result }}" = "skipped" ]; then + echo "::error:: Build job was skipped — no builds executed." + exit 1 + fi + if [ "${{ needs.build.result }}" != "success" ]; then + echo "::error:: ❌ One or more builds failed." + exit 1 + fi + echo "::notice:: ✅ All builds ran and passed." diff --git a/Rakefile b/Rakefile index 460c4237a2..6f5a9c3c76 100644 --- a/Rakefile +++ b/Rakefile @@ -28,24 +28,53 @@ namespace :each do task :default do foreach_gem('bundle exec rake') end + + task :build do + foreach_gem('bundle exec rake build') + end + + task :install do + path = File.join(Dir.pwd, "vendor", "bundle") + foreach_gem([ + "bundle config set path #{path}", + "bundle config set clean false", + "bundle install --jobs 4 --retry 3" + ]) + end end task each: 'each:default' +task build: ['each:build'] +task install: ['each:install'] +task yard: ['each:yard'] + task default: [:each] -def foreach_gem(cmd) - Dir.glob("**/opentelemetry-*.gemspec") do |gemspec| +EXCLUDED_DIRS = %w[vendor] + +def foreach_gem(cmds) + cmds = Array(cmds) # string → ["string"], array stays array + gemspecs = + Dir.glob("**/opentelemetry-*.gemspec") + .reject do |path| + EXCLUDED_DIRS.any? do |d| + path.include?("/#{d}/") || path.start_with?("#{d}/") + end + end + .sort + + gemspecs.each do |gemspec| name = File.basename(gemspec, ".gemspec") dir = File.dirname(gemspec) puts "**** Entering #{dir}" Dir.chdir(dir) do if defined?(Bundler) - Bundler.with_clean_env do - sh(cmd) + Bundler.with_unbundled_env do + cmds.each { |cmd| sh(cmd) } end else - sh(cmd) + cmds.each { |cmd| sh(cmd) } end end end diff --git a/sampler/xray/README.md b/sampler/xray/README.md index c17ebf9d3b..fd3406d725 100644 --- a/sampler/xray/README.md +++ b/sampler/xray/README.md @@ -1,4 +1,4 @@ -# opentelemetry-sampler-xray +# OpenTelemetry::Sampler::XRay The `opentelemetry-sampler-xray` gem contains the AWS X-Ray Remote Sampler for OpenTelemetry.