diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b18fd29 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'weekly' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e910cfb..da39e8b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,162 +1,180 @@ name: JRuby Dev Builds on: + workflow_dispatch: push: tags: - '*' schedule: - cron: '0 19 * * *' jobs: + prepare: + name: Check if the latest jruby snapshot is already built + runs-on: ubuntu-latest + outputs: + should_build: ${{ steps.check_commit.outputs.result }} + url: ${{ steps.url.outputs.url }} + steps: + - name: Clone to get find-jruby-head-url-nokogiri.rb + uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ruby + bundler-cache: true + - name: Get latest jruby nightly archive url + id: url + run: | + echo "url=$(bundle exec ruby find-jruby-head-url-nokogiri.rb)" | tee -a "$GITHUB_OUTPUT" + - name: Check if latest commit already built + uses: actions/github-script@v7 + id: check_commit + with: + script: | + const latestSnapshotUrl = "${{ steps.url.outputs.url }}" + const { owner, repo } = context.repo + let { data: release } = await github.rest.repos.getLatestRelease({ owner, repo }) + const latestTaggedUrl = release.body.split(/\s+/)[1] + console.log(`Latest snapshot url: ${latestSnapshotUrl}`) + console.log(`Latest tagged url: ${latestTaggedUrl}`) + if (latestSnapshotUrl === latestTaggedUrl) { + return 'false' + } else { + return 'true' + } + result-encoding: string + release: name: Create GitHub Release + needs: [prepare] + if: needs.prepare.outputs.should_build == 'true' runs-on: ubuntu-latest + outputs: + tag: ${{ steps.tag.outputs.tag }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - if: github.event_name == 'schedule' - - name: Create tag - id: create_tag - shell: bash + if: github.event_name != 'push' + + - name: Set tag name + id: tag run: | - if [[ "${{ github.event_name }}" == "schedule" ]]; then - tag=builds-$(date +%Y%m%d-%H%M%S) + if [[ "${{ github.event_name }}" != "push" ]]; then + tag=v$(date +%Y%m%d.%H%M%S) else tag=$(basename "${{ github.ref }}") fi - echo "::set-output name=tag::$tag" + echo "tag=$tag" >> $GITHUB_OUTPUT - name: Create Release - id: create_release - uses: actions/create-release@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ steps.create_tag.outputs.tag }} - release_name: ${{ steps.create_tag.outputs.tag }} - draft: true - prerelease: false - - name: Create artifact files - shell: bash + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} run: | - mkdir info - echo "${{ steps.create_release.outputs.id }}" > info/release_id - echo "${{ steps.create_release.outputs.upload_url }}" > info/upload_url - - uses: actions/upload-artifact@v1 - with: - name: info - path: info + tag="${{ steps.tag.outputs.tag }}" + gh release create --draft "$tag" --title "$tag" build: - needs: [release] + needs: [prepare, release] strategy: fail-fast: false matrix: - os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04, macos-latest, windows-latest ] + os: [ ubuntu-22.04, ubuntu-24.04, ubuntu-22.04-arm, ubuntu-24.04-arm, macos-13, macos-14, windows-2022, windows-11-arm ] runs-on: ${{ matrix.os }} + outputs: + commit: ${{ steps.latest_commit.outputs.commit }} steps: - - uses: actions/download-artifact@v1 - with: - name: info - - name: Set upload_url - id: upload_info + - name: Set platform + id: platform shell: bash run: | - upload_url=$(cat info/upload_url) - echo "::set-output name=upload_url::$upload_url" + platform=${{ matrix.os }} + platform=${platform/macos-13/macos-latest} + platform=${platform/macos-14/macos-13-arm64} + platform=${platform/windows-2022/windows-latest} + platform=${platform/windows-11-arm/windows-arm64} + platform=${platform/%-arm/-arm64} + echo "platform=$platform" >> $GITHUB_OUTPUT # Build - - uses: actions/checkout@v2 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.6 + - name: Clone to get test/Gemfile + uses: actions/checkout@v4 - name: Download latest jruby nightly archive shell: bash - run: | - url=$(ruby find-jruby-head-url.rb) - echo "$url" - curl --fail -L -o jruby-head.tar.gz "$url" + run: curl --fail -L -o jruby-head.tar.gz "${{ needs.prepare.outputs.url }}" - uses: eregon/clean-path@v1 with: regexp: '\bruby\b' - run: tar xf jruby-head.tar.gz if: "!startsWith(matrix.os, 'windows')" + # NOTE: Keep the logic from here in sync with ruby-builder's buildJRubyWindows job # Extracting must be done in the native shell: https://github.com/MSP-Greg/ruby-setup-ruby/issues/1 - # We need to use to use the system tar, the Git tar seems basically broken + # We need to use to use the system tar, the Git tar seems basically broken. + # And `mv dir /c/...` also removes jruby.exe, so we need to avoid that. - run: C:\windows\system32\tar.exe xf jruby-head.tar.gz if: startsWith(matrix.os, 'windows') - - name: Rename to jruby-head + - name: Check bin/ and rename to jruby-head shell: bash run: | ls -l jruby-*-SNAPSHOT/bin mv jruby-*-SNAPSHOT jruby-head ls -l jruby-head/bin - - name: Add ruby alias - if: "!startsWith(matrix.os, 'windows')" - run: | - cd jruby-head/bin - ln -s jruby ruby - - name: Add ruby alias (Windows) - if: startsWith(matrix.os, 'windows') - shell: bash - run: | - cd jruby-head/bin - # Copy bash launcher, so 'ruby' works in bash - cp jruby ruby - # Create ruby.bat, so 'ruby' works in pwsh - echo -en "@ECHO OFF\r\n@\"%~dp0jruby.exe\" %*\r\n" > ruby.bat - name: Create archive - run: tar czf jruby-head-${{ matrix.os }}.tar.gz jruby-head - - - name: Install Bundler if needed - shell: bash - run: | - if [ ! -e jruby-head/bin/bundle ]; then - export PATH="$PWD/jruby-head/bin:$PATH" - gem env - gem install bundler -v '~> 1' --no-document - fi + run: tar czf jruby-head-${{ steps.platform.outputs.platform }}.tar.gz jruby-head # Test - run: echo "$PWD/jruby-head/bin" >> $GITHUB_PATH + if: "!startsWith(matrix.os, 'windows')" + - run: echo "$($pwd.Path)\jruby-head\bin" | Out-File -FilePath $Env:GITHUB_PATH -Encoding utf8 -Append + if: startsWith(matrix.os, 'windows') + - run: which ruby + if: "!startsWith(matrix.os, 'windows')" + - run: where.exe ruby + if: startsWith(matrix.os, 'windows') + - run: echo $Env:Path + + # JAVA_HOME_21_AARCH64 - https://github.com/actions/partner-runner-images/blob/main/images/arm-windows-11-image.md#java + # JAVA_HOME_21_arm64 - https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md#java + # JAVA_HOME_21_X64 - https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md#java + - name: switch to Java 21 for verification + run: echo "JAVA_HOME=${JAVA_HOME_21_AARCH64:-${JAVA_HOME_21_arm64:-${JAVA_HOME_21_X64:-}}}" >> "$GITHUB_ENV" + shell: bash - run: ruby --version + - run: ruby -e 'raise unless RUBY_ENGINE == %{jruby}' - run: gem --version - run: rake --version - - run: ruby -ropen-uri -e 'puts open(%{https://rubygems.org/}) { |f| f.read(1024) }' + - run: ruby -ropen-uri -e 'puts URI.send(:open, %{https://rubygems.org/}) { |f| f.read(1024) }' - run: gem install json:2.2.0 --no-document - run: bundle --version + working-directory: test - run: bundle install + working-directory: test - run: bundle exec rake --version + working-directory: test + + - name: Set latest_commit + id: latest_commit + run: echo "commit=$(ruby -e 'puts JRUBY_REVISION')" >> $GITHUB_OUTPUT - name: Upload Built Ruby - uses: actions/upload-release-asset@v1 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.upload_info.outputs.upload_url }} - asset_path: jruby-head-${{ matrix.os }}.tar.gz - asset_name: jruby-head-${{ matrix.os }}.tar.gz - asset_content_type: application/gzip + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: gh release upload "${{ needs.release.outputs.tag }}" "jruby-head-${{ steps.platform.outputs.platform }}.tar.gz" - metadata: + publish: name: Publish Release - needs: [build] + needs: [prepare, release, build] runs-on: ubuntu-latest steps: - - uses: actions/download-artifact@v1 - with: - name: info - - name: Set publish_info - id: publish_info - shell: bash - run: | - release_id=$(cat info/release_id) - echo "::set-output name=release_id::$release_id" - - uses: eregon/publish-release@v1 + - name: Publish Release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - release_id: ${{ steps.publish_info.outputs.release_id }} + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + run: | + body="jruby/jruby@${{ needs.build.outputs.commit }} ${{ needs.prepare.outputs.url }}" + gh release edit "${{ needs.release.outputs.tag }}" --draft=false --notes "$body" - uses: eregon/keep-last-n-releases@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: n: 3 + remove_tags_without_release: true diff --git a/Gemfile b/Gemfile index 0012c31..bcf5c12 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,3 @@ -# Used for testing source 'https://rubygems.org' -gem "rake" -gem "path" -gem "json", "2.2.0" +gem 'nokogiri' diff --git a/find-jruby-head-url-nokogiri.rb b/find-jruby-head-url-nokogiri.rb index e3f147a..a2f9e0b 100644 --- a/find-jruby-head-url-nokogiri.rb +++ b/find-jruby-head-url-nokogiri.rb @@ -1,7 +1,8 @@ require 'open-uri' +require 'rubygems' require 'nokogiri' -base_url = 'https://oss.sonatype.org/content/repositories/snapshots/org/jruby/jruby-dist' +base_url = 'https://central.sonatype.com/repository/maven-snapshots/org/jruby/jruby-dist' index_url = "#{base_url}/maven-metadata.xml" STDERR.puts index_url @@ -9,7 +10,9 @@ STDERR.puts xml versions = Nokogiri::XML(xml).css('version').map(&:text) -most_recent = (versions - %w[9000.dev-SNAPSHOT]).last + +versions.delete('9000.dev-SNAPSHOT') +most_recent = versions.max_by { |v| Gem::Version.new(v) } builds_url = "#{base_url}/#{most_recent}/maven-metadata.xml" STDERR.puts builds_url diff --git a/find-jruby-head-url.rb b/find-jruby-head-url.rb deleted file mode 100644 index 1546759..0000000 --- a/find-jruby-head-url.rb +++ /dev/null @@ -1,81 +0,0 @@ -require 'open-uri' - -module MicroXMLParser - HEADER = %r{<\?xml\s.+\?>\n} - ATTRIBUTE = %r{(\w+)="([^"]+)"} - OPEN_TAG = %r{<(\w+)((?:\s+#{ATTRIBUTE})*)>} - CLOSE_TAG = %r{} - TEXT = %r{([^<]*)} - - def self.parse(xml) - xml = xml.strip - raise xml unless xml.start_with? HEADER - xml = xml[$&.size..-1].strip - value, rest = rec(xml) - raise rest unless rest.empty? - value - end - - def self.rec(xml) - xml = xml.strip - if xml.start_with? OPEN_TAG - entries = [] - while xml.start_with? OPEN_TAG - tag, attributes = $1, $2 - xml = xml[$&.size..-1].strip - - until attributes.empty? - attributes = attributes.strip - raise attributes unless attributes.start_with? ATTRIBUTE - key, value = $1, $2 - attributes = attributes[$&.size..-1] - entries << { key.to_sym => value } - end - - value, xml = rec(xml) - entries << { tag.to_sym => value } - - close_tag = "" - raise "Missing close tag #{close_tag}: #{xml}" unless xml.start_with? close_tag - xml = xml[close_tag.size..-1].strip - end - - keys = entries.map { |entry| entry.first.first } - if keys == keys.uniq - entries = entries.inject({}, :merge) - end - - [entries, xml] - elsif xml.start_with? TEXT - text = $1 - xml = xml[$&.size..-1] - [text, xml] - else - raise xml - end - end -end - -base_url = 'https://oss.sonatype.org/content/repositories/snapshots/org/jruby/jruby-dist' -index_url = "#{base_url}/maven-metadata.xml" - -STDERR.puts index_url -xml = URI.open(index_url, &:read) -STDERR.puts xml - -parsed = MicroXMLParser.parse(xml) -versions = parsed.dig(:metadata, :versioning, :versions).map { |e| e[:version] } -most_recent = (versions - %w[9000.dev-SNAPSHOT]).last - -builds_url = "#{base_url}/#{most_recent}/maven-metadata.xml" -STDERR.puts builds_url -xml = URI.open(builds_url, &:read) -STDERR.puts xml - -parsed = MicroXMLParser.parse(xml) -last_build = parsed.dig(:metadata, :versioning, :snapshotVersions).map { |e| e[:snapshotVersion] }.select { |node| - node[:classifier] == 'bin' and node[:extension] == 'tar.gz' -}.map { |node| node[:value] }.last - -final_url = "#{base_url}/#{most_recent}/jruby-dist-#{last_build}-bin.tar.gz" -puts final_url diff --git a/test/Gemfile b/test/Gemfile new file mode 100644 index 0000000..9900a98 --- /dev/null +++ b/test/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org' + +gem 'rake' +gem 'path' +gem 'json', '2.2.0' diff --git a/trigger.sh b/trigger.sh index e90e757..fd13c27 100755 --- a/trigger.sh +++ b/trigger.sh @@ -1,4 +1,4 @@ #!/bin/sh -tag=builds-$(date +%Y%m%d-%H%M%S) +tag=v$(date +%Y%m%d.%H%M%S) git tag "$tag" git push origin "$tag"