diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95f65e9..9b578c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,11 +6,23 @@ on: version: required: true type: string + self_hosted: + description: Build x86_64_linux on the self-hosted runners instead of GitHub's + required: false + type: boolean + default: false workflow_call: inputs: version: required: true type: string + # The self-hosted runners are x64 Ubuntu VMs at home, so only x86_64_linux can move + # there; arm64_linux always builds on GitHub's hosted arm runner. Off by default so + # pull requests, which anyone can open on this public repository, never run on them. + self_hosted: + required: false + type: boolean + default: false permissions: contents: read @@ -41,16 +53,23 @@ jobs: - id: matrix env: YJIT: ${{ steps.info.outputs.yjit }} + SELF_HOSTED: ${{ inputs.self_hosted }} run: | # Both variants per target when the series has YJIT, otherwise one build per target # (bin/package names it without the .no_yjit suffix). if [[ "$YJIT" == "true" ]]; then yjits='[true, false]'; else yjits='[false]'; fi - echo "linux=$(jq -c -n --argjson yjits "$yjits" '{include: [ - {runner: "ubuntu-22.04", target: "x86_64_linux"}, + if [[ "$SELF_HOSTED" == "true" ]]; then x86='["self-hosted", "linux", "x64"]'; else x86='"ubuntu-22.04"'; fi + # Each target's pinned manylinux container is resolved here so the build jobs need + # no host Ruby: ruby/setup-ruby on self-hosted runners installs into the shared + # /opt/hostedtoolcache, and two jobs extracting the same Ruby there at once race. + containers=$(ruby -ryaml -rjson -e 'puts YAML.load_file("recipes/targets.yml").fetch("targets").transform_values { |t| t.fetch("container") }.to_json') + echo "linux=$(jq -c -n --argjson yjits "$yjits" --argjson x86 "$x86" --argjson containers "$containers" '{include: [ + {runner: $x86, target: "x86_64_linux"}, {runner: "ubuntu-22.04-arm", target: "arm64_linux"} - ] | map(. as $t | $yjits[] | $t + {yjit: .})}')" >> "$GITHUB_OUTPUT" + ] | map(. as $t | $yjits[] | $t + {yjit: ., container: $containers[$t.target]})}')" >> "$GITHUB_OUTPUT" build-linux: + name: build-linux (${{ matrix.target }}, yjit=${{ matrix.yjit }}) needs: plan strategy: fail-fast: false @@ -58,24 +77,13 @@ jobs: runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - uses: ruby/setup-ruby@v1 - with: - ruby-version: .ruby-version - - - name: Resolve target container - id: target - env: - TARGET: ${{ matrix.target }} - run: | - container=$(ruby -ryaml -e 'puts YAML.load_file("recipes/targets.yml").fetch("targets").fetch(ENV.fetch("TARGET")).fetch("container")') - echo "container=$container" >> "$GITHUB_OUTPUT" - name: Build portable Ruby in manylinux env: VERSION: ${{ inputs.version }} TARGET: ${{ matrix.target }} YJIT: ${{ matrix.yjit }} - CONTAINER: ${{ steps.target.outputs.container }} + CONTAINER: ${{ matrix.container }} run: | set -euxo pipefail docker pull "$CONTAINER" @@ -118,9 +126,18 @@ jobs: fi bin/package "$VERSION" --target "$TARGET" "$yjit_arg" --output rubies - chown -R "$(stat -c %u /work):$(stat -c %g /work)" rubies .build .cache || true ' + # The container runs as root, so everything it wrote into the workspace is root-owned. + # On a self-hosted runner the workspace outlives the job, and the next checkout's clean + # would fail on those files, so hand them back to the runner user even after a failed + # build. + - name: Fix workspace ownership + if: always() + env: + CONTAINER: ${{ matrix.container }} + run: docker run --rm -v "$PWD:/work" "$CONTAINER" chown -R "$(id -u):$(id -g)" /work + - name: Upload portable Ruby uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6de6250..3683213 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,11 @@ on: required: false type: boolean default: false + self_hosted: + description: 'Build x86_64_linux on the self-hosted runners (arm64 stays on GitHub)' + required: false + type: boolean + default: true env: # Revision releases of a version to keep after publishing a new one: the current build @@ -119,6 +124,7 @@ jobs: uses: ./.github/workflows/build.yml with: version: ${{ inputs.version }} + self_hosted: ${{ inputs.self_hosted }} combine-hashes: needs: build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f876740..1b9306c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,6 +29,8 @@ jobs: ruby -c libexec/validate_recipes.rb ruby -c libexec/update_ruby_recipe.rb + # Stays on GitHub's runners (build.yml's self_hosted defaults to false): a pull request + # can come from anyone, and the self-hosted runners are machines at home. build: needs: syntax if: github.event_name == 'pull_request'