diff --git a/.github/workflows/ci-cd-contributor.yml b/.github/workflows/ci-cd-contributor.yml new file mode 100644 index 0000000..5ecd65d --- /dev/null +++ b/.github/workflows/ci-cd-contributor.yml @@ -0,0 +1,368 @@ +# WARNING: DO NOT EDIT THIS FILE!!! +# +# This file is autogenerated from .github/workflows/ci-cd-contributor.yml.erb +# by ./internal-scripts/generate-ci-cd-yaml.rb. +# Please edit the .erb file instead, then regenerate YAML +# by running that script. +# +# TIP: run this on your development machine to ensure generate-ci-cd-yaml.rb +# is run automatically as a Git pre-commit hook: +# +# git config core.hooksPath .githooks + +name: 'CI/CD: contributor' + +on: + push: + paths-ignore: + - '**.md' + - 'dev-handbook/**' + pull_request: + paths-ignore: + - '**.md' + - 'dev-handbook/**' + workflow_dispatch: + +jobs: + lint: + name: Check whether workflow is up-to-date + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + - name: Check + run: ./internal-scripts/ci-cd/check-workflow-uptodate/check.sh + + + build_images: + name: Build Docker images + needs: lint + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + steps: + - uses: actions/checkout@v4 + + - name: 'Build Docker image [ubuntu-24.04]' + run: ./internal-scripts/ci-cd/build-docker-images/build.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'ubuntu-24.04-v2' + SOURCE_DIR: 'environments/ubuntu-24.04' + - name: 'Dump Docker image [ubuntu-24.04]' + run: ./internal-scripts/ci-cd/build-docker-images/dump-image.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'ubuntu-24.04-v2' + - name: 'Upload Docker image artifact [ubuntu-24.04]' + uses: actions/upload-artifact@v4 + with: + name: 'docker-image-ubuntu-24.04' + path: output + - name: Clean up Docker image output + run: rm -rf output + + - name: 'Build Docker image [el-9]' + run: ./internal-scripts/ci-cd/build-docker-images/build.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'el-9-v2' + SOURCE_DIR: 'environments/el-9' + - name: 'Dump Docker image [el-9]' + run: ./internal-scripts/ci-cd/build-docker-images/dump-image.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'el-9-v2' + - name: 'Upload Docker image artifact [el-9]' + uses: actions/upload-artifact@v4 + with: + name: 'docker-image-el-9' + path: output + - name: Clean up Docker image output + run: rm -rf output + + - name: 'Build Docker image [utility]' + run: ./internal-scripts/ci-cd/build-docker-images/build.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'utility-v3' + SOURCE_DIR: 'environments/utility' + - name: 'Dump Docker image [utility]' + run: ./internal-scripts/ci-cd/build-docker-images/dump-image.sh + env: + IMAGE_NAME: 'ghcr.io/fullstaq-ruby/server-edition-ci-images' + IMAGE_TAG: 'utility-v3' + - name: 'Upload Docker image artifact [utility]' + uses: actions/upload-artifact@v4 + with: + name: 'docker-image-utility' + path: output + - name: Clean up Docker image output + run: rm -rf output + + + build_packages: + name: Build packages + needs: build_images + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + + ### Download and load Docker images ### + + - name: 'Download Docker image artifact [ubuntu-24.04]' + uses: actions/download-artifact@v4 + with: + name: 'docker-image-ubuntu-24.04' + path: docker-image-ubuntu-24.04 + - name: 'Load Docker image [ubuntu-24.04]' + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-ubuntu-24.04/image.tar.zst + + - name: 'Download Docker image artifact [el-9]' + uses: actions/download-artifact@v4 + with: + name: 'docker-image-el-9' + path: docker-image-el-9 + - name: 'Load Docker image [el-9]' + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-el-9/image.tar.zst + + - name: 'Download Docker image artifact [utility]' + uses: actions/download-artifact@v4 + with: + name: 'docker-image-utility' + path: docker-image-utility + - name: 'Load Docker image [utility]' + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-utility/image.tar.zst + + ### Download sources ### + + - name: Download Ruby source + run: curl -fsSL -o ruby-src.tar.gz 'https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.3.tar.gz' + - name: Download Jemalloc source + run: curl -fsSL -o jemalloc-src.tar.bz2 'https://github.com/jemalloc/jemalloc/releases/download/3.6.0/jemalloc-3.6.0.tar.bz2' + - name: Clone Rbenv source + run: | + git clone 'https://github.com/fullstaq-ruby/rbenv.git' rbenv-src + cd rbenv-src + git checkout 'fbaa15993171bf' + + ### Build Jemalloc ### + + - name: 'Build Jemalloc [ubuntu-24.04]' + run: | + ./build-jemalloc \ + -n 'ubuntu-24.04' \ + -s "$(pwd)/jemalloc-src.tar.bz2" \ + -o "$(pwd)/jemalloc-bin-ubuntu-24.04.tar.gz" \ + -j 2 + + - name: 'Build Jemalloc [el-9]' + run: | + ./build-jemalloc \ + -n 'el-9' \ + -s "$(pwd)/jemalloc-src.tar.bz2" \ + -o "$(pwd)/jemalloc-bin-el-9.tar.gz" \ + -j 2 + + ### Build Ruby binaries ### + + - name: 'Build Ruby binaries [ubuntu-24.04/normal]' + run: | + ./build-ruby \ + -n 'ubuntu-24.04' \ + -s "$(pwd)/ruby-src.tar.gz" \ + -v '4.0' \ + -o "$(pwd)/ruby-bin-ubuntu-24.04-normal.tar.gz" \ + -j 2 + + - name: 'Build Ruby binaries [ubuntu-24.04/jemalloc]' + run: | + ./build-ruby \ + -n 'ubuntu-24.04' \ + -s "$(pwd)/ruby-src.tar.gz" \ + -v '4.0' \ + -o "$(pwd)/ruby-bin-ubuntu-24.04-jemalloc.tar.gz" \ + -m "$(pwd)/jemalloc-bin-ubuntu-24.04.tar.gz" \ + -j 2 + + - name: 'Build Ruby binaries [el-9/normal]' + run: | + ./build-ruby \ + -n 'el-9' \ + -s "$(pwd)/ruby-src.tar.gz" \ + -v '4.0' \ + -o "$(pwd)/ruby-bin-el-9-normal.tar.gz" \ + -j 2 + + - name: 'Build Ruby binaries [el-9/jemalloc]' + run: | + ./build-ruby \ + -n 'el-9' \ + -s "$(pwd)/ruby-src.tar.gz" \ + -v '4.0' \ + -o "$(pwd)/ruby-bin-el-9-jemalloc.tar.gz" \ + -m "$(pwd)/jemalloc-bin-el-9.tar.gz" \ + -j 2 + + - name: Create packages directory + run: mkdir -p packages + + ### Build Ruby packages ### + + - name: 'Build Ruby package [ubuntu-24.04/normal]' + run: | + ./build-ruby-deb \ + -b "$(pwd)/ruby-bin-ubuntu-24.04-normal.tar.gz" \ + -o "$(pwd)/packages/fullstaq-ruby-4.0_2-ubuntu-24.04_amd64.deb" \ + -r '2' + + - name: 'Build Ruby package [ubuntu-24.04/jemalloc]' + run: | + ./build-ruby-deb \ + -b "$(pwd)/ruby-bin-ubuntu-24.04-jemalloc.tar.gz" \ + -o "$(pwd)/packages/fullstaq-ruby-4.0-jemalloc_2-ubuntu-24.04_amd64.deb" \ + -r '2' + + - name: 'Build Ruby package [el-9/normal]' + run: | + ./build-ruby-rpm \ + -b "$(pwd)/ruby-bin-el-9-normal.tar.gz" \ + -o "$(pwd)/packages/fullstaq-ruby-4.0-rev2-el9.x86_64.rpm" \ + -r '2' + + - name: 'Build Ruby package [el-9/jemalloc]' + run: | + ./build-ruby-rpm \ + -b "$(pwd)/ruby-bin-el-9-jemalloc.tar.gz" \ + -o "$(pwd)/packages/fullstaq-ruby-4.0-jemalloc-rev2-el9.x86_64.rpm" \ + -r '2' + + ### Build Rbenv packages ### + + - name: Build Rbenv DEB + run: | + ./build-rbenv-deb \ + -s "$(pwd)/rbenv-src" \ + -o "$(pwd)/packages/fullstaq-rbenv_1.1.2-16-1_all.deb" \ + -n '1.1.2-16' \ + -r '1' + - name: Build Rbenv RPM + run: | + ./build-rbenv-rpm \ + -s "$(pwd)/rbenv-src" \ + -o "$(pwd)/packages/fullstaq-rbenv-1.1.2_16-1.noarch.rpm" \ + -n '1.1.2-16' \ + -r '1' + + ### Build common packages ### + + - name: Build common DEB + run: | + ./build-common-deb \ + -o "$(pwd)/packages/fullstaq-ruby-common_1.0-1_all.deb" + - name: Build common RPM + run: | + ./build-common-rpm \ + -o "$(pwd)/packages/fullstaq-ruby-common-1.0-1.noarch.rpm" + + ### Upload all packages ### + + - name: Upload packages + uses: actions/upload-artifact@v4 + with: + name: contributor-packages + path: packages + + + test_packages: + name: 'Test [${{ matrix.distro }}/${{ matrix.variant }}]' + needs: build_packages + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + - distro: 'ubuntu-24.04' + variant: 'normal' + test_image: 'ubuntu:24.04' + package_format: 'DEB' + - distro: 'ubuntu-24.04' + variant: 'jemalloc' + test_image: 'ubuntu:24.04' + package_format: 'DEB' + - distro: 'el-9' + variant: 'normal' + test_image: 'rockylinux:9' + package_format: 'RPM' + - distro: 'el-9' + variant: 'jemalloc' + test_image: 'rockylinux:9' + package_format: 'RPM' + steps: + - uses: actions/checkout@v4 + + - name: Download packages + uses: actions/download-artifact@v4 + with: + name: contributor-packages + path: packages + + - name: Download utility Docker image + uses: actions/download-artifact@v4 + with: + name: 'docker-image-utility' + path: docker-image-utility + - name: Load utility Docker image + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-utility/image.tar.zst + + - name: Determine Ruby package filename + id: ruby_pkg + run: | + VARIANT="${{ matrix.variant }}" + DISTRO="${{ matrix.distro }}" + FORMAT="${{ matrix.package_format }}" + if [ "$VARIANT" = "normal" ]; then + VARIANT_SUFFIX="" + else + VARIANT_SUFFIX="-${VARIANT}" + fi + if [ "$FORMAT" = "DEB" ]; then + FILENAME="fullstaq-ruby-4.0${VARIANT_SUFFIX}_2-${DISTRO}_amd64.deb" + else + SANITIZED_DISTRO=$(echo "$DISTRO" | tr -d '-') + FILENAME="fullstaq-ruby-4.0${VARIANT_SUFFIX}-rev2-${SANITIZED_DISTRO}.x86_64.rpm" + fi + echo "filename=${FILENAME}" >> "$GITHUB_OUTPUT" + + - name: Test DEBs + if: matrix.package_format == 'DEB' + run: | + ./test-debs \ + -i '${{ matrix.test_image }}' \ + -v '${{ matrix.variant }}' \ + -r "$(pwd)/packages/${{ steps.ruby_pkg.outputs.filename }}" \ + -b "$(pwd)/packages/fullstaq-rbenv_1.1.2-16-1_all.deb" \ + -c "$(pwd)/packages/fullstaq-ruby-common_1.0-1_all.deb" + - name: Test RPMs + if: matrix.package_format == 'RPM' + run: | + ./test-rpms \ + -i '${{ matrix.test_image }}' \ + -v '${{ matrix.variant }}' \ + -r "$(pwd)/packages/${{ steps.ruby_pkg.outputs.filename }}" \ + -b "$(pwd)/packages/fullstaq-rbenv-1.1.2_16-1.noarch.rpm" \ + -c "$(pwd)/packages/fullstaq-ruby-common-1.0-1.noarch.rpm" diff --git a/.github/workflows/ci-cd-contributor.yml.erb b/.github/workflows/ci-cd-contributor.yml.erb new file mode 100644 index 0000000..bbb32b7 --- /dev/null +++ b/.github/workflows/ci-cd-contributor.yml.erb @@ -0,0 +1,290 @@ +<%= editing_warning_comment('ci-cd-contributor') %> +<%- rpv = latest_ruby_package_version -%> + +name: 'CI/CD: contributor' + +on: + push: + paths-ignore: + - '**.md' + - 'dev-handbook/**' + pull_request: + paths-ignore: + - '**.md' + - 'dev-handbook/**' + workflow_dispatch: + +jobs: + lint: + name: Check whether workflow is up-to-date + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + - name: Check + run: ./internal-scripts/ci-cd/check-workflow-uptodate/check.sh + + + build_images: + name: Build Docker images + needs: lint + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + steps: + - uses: actions/checkout@v4 + + <%- contributor_distributions.each do |distro| -%> + <%- image = docker_images.find { |img| img[:id] == distro[:name] } -%> + - name: 'Build Docker image [<%= distro[:name] %>]' + run: ./internal-scripts/ci-cd/build-docker-images/build.sh + env: + IMAGE_NAME: '<%= image[:name] %>' + IMAGE_TAG: '<%= image[:tag] %>' + SOURCE_DIR: 'environments/<%= image[:id] %>' + - name: 'Dump Docker image [<%= distro[:name] %>]' + run: ./internal-scripts/ci-cd/build-docker-images/dump-image.sh + env: + IMAGE_NAME: '<%= image[:name] %>' + IMAGE_TAG: '<%= image[:tag] %>' + - name: 'Upload Docker image artifact [<%= distro[:name] %>]' + uses: actions/upload-artifact@v4 + with: + name: '<%= docker_image_artifact_name(distro[:name]) %>' + path: output + - name: Clean up Docker image output + run: rm -rf output + + <%- end -%> + <%- utility_image = docker_images.find { |img| img[:id] == 'utility' } -%> + - name: 'Build Docker image [utility]' + run: ./internal-scripts/ci-cd/build-docker-images/build.sh + env: + IMAGE_NAME: '<%= utility_image[:name] %>' + IMAGE_TAG: '<%= utility_image[:tag] %>' + SOURCE_DIR: 'environments/utility' + - name: 'Dump Docker image [utility]' + run: ./internal-scripts/ci-cd/build-docker-images/dump-image.sh + env: + IMAGE_NAME: '<%= utility_image[:name] %>' + IMAGE_TAG: '<%= utility_image[:tag] %>' + - name: 'Upload Docker image artifact [utility]' + uses: actions/upload-artifact@v4 + with: + name: '<%= docker_image_artifact_name('utility') %>' + path: output + - name: Clean up Docker image output + run: rm -rf output + + + build_packages: + name: Build packages + needs: build_images + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + + ### Download and load Docker images ### + + <%- contributor_distributions.each do |distro| -%> + - name: 'Download Docker image artifact [<%= distro[:name] %>]' + uses: actions/download-artifact@v4 + with: + name: '<%= docker_image_artifact_name(distro[:name]) %>' + path: docker-image-<%= distro[:name] %> + - name: 'Load Docker image [<%= distro[:name] %>]' + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-<%= distro[:name] %>/image.tar.zst + + <%- end -%> + - name: 'Download Docker image artifact [utility]' + uses: actions/download-artifact@v4 + with: + name: '<%= docker_image_artifact_name('utility') %>' + path: docker-image-utility + - name: 'Load Docker image [utility]' + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-utility/image.tar.zst + + ### Download sources ### + + - name: Download Ruby source + run: curl -fsSL -o ruby-src.tar.gz '<%= ruby_source_url(rpv[:full_version]) %>' + - name: Download Jemalloc source + run: curl -fsSL -o jemalloc-src.tar.bz2 '<%= jemalloc_source_url %>' + - name: Clone Rbenv source + run: | + git clone '<%= config[:rbenv][:repo] %>' rbenv-src + cd rbenv-src + git checkout '<%= config[:rbenv][:ref] %>' + + ### Build Jemalloc ### + + <%- contributor_distributions.each do |distro| -%> + - name: 'Build Jemalloc [<%= distro[:name] %>]' + run: | + ./build-jemalloc \ + -n '<%= distro[:name] %>' \ + -s "$(pwd)/jemalloc-src.tar.bz2" \ + -o "$(pwd)/jemalloc-bin-<%= distro[:name] %>.tar.gz" \ + -j 2 + + <%- end -%> + ### Build Ruby binaries ### + + <%- contributor_distributions.each do |distro| -%> + <%- variants_for_ruby_version(rpv).each do |variant| -%> + - name: 'Build Ruby binaries [<%= distro[:name] %>/<%= variant[:name] %>]' + run: | + ./build-ruby \ + -n '<%= distro[:name] %>' \ + -s "$(pwd)/ruby-src.tar.gz" \ + -v '<%= rpv[:id] %>' \ + -o "$(pwd)/ruby-bin-<%= distro[:name] %>-<%= variant[:name] %>.tar.gz" \ + <%- if variant[:name] == 'jemalloc' -%> + -m "$(pwd)/jemalloc-bin-<%= distro[:name] %>.tar.gz" \ + <%- elsif variant[:name] == 'malloctrim' -%> + -t \ + <%- end -%> + -j 2 + + <%- end -%> + <%- end -%> + - name: Create packages directory + run: mkdir -p packages + + ### Build Ruby packages ### + + <%- contributor_distributions.each do |distro| -%> + <%- variants_for_ruby_version(rpv).each do |variant| -%> + <%- pkg_basename = ruby_package_basename(rpv, distro, variant) -%> + - name: 'Build Ruby package [<%= distro[:name] %>/<%= variant[:name] %>]' + run: | + <%- if distro[:package_format] == :DEB -%> + ./build-ruby-deb \ + <%- else -%> + ./build-ruby-rpm \ + <%- end -%> + -b "$(pwd)/ruby-bin-<%= distro[:name] %>-<%= variant[:name] %>.tar.gz" \ + -o "$(pwd)/packages/<%= pkg_basename %>" \ + -r '<%= rpv[:package_revision] %>' + + <%- end -%> + <%- end -%> + ### Build Rbenv packages ### + + - name: Build Rbenv DEB + run: | + ./build-rbenv-deb \ + -s "$(pwd)/rbenv-src" \ + -o "$(pwd)/packages/<%= rbenv_package_basename(:DEB) %>" \ + -n '<%= rbenv_version %>' \ + -r '<%= rbenv_package_revision %>' + - name: Build Rbenv RPM + run: | + ./build-rbenv-rpm \ + -s "$(pwd)/rbenv-src" \ + -o "$(pwd)/packages/<%= rbenv_package_basename(:RPM) %>" \ + -n '<%= rbenv_version %>' \ + -r '<%= rbenv_package_revision %>' + + ### Build common packages ### + + - name: Build common DEB + run: | + ./build-common-deb \ + -o "$(pwd)/packages/<%= common_package_basename(:DEB) %>" + - name: Build common RPM + run: | + ./build-common-rpm \ + -o "$(pwd)/packages/<%= common_package_basename(:RPM) %>" + + ### Upload all packages ### + + - name: Upload packages + uses: actions/upload-artifact@v4 + with: + name: contributor-packages + path: packages + + + test_packages: + name: 'Test [${{ matrix.distro }}/${{ matrix.variant }}]' + needs: build_packages + runs-on: ubuntu-24.04 + if: github.event_name == 'pull_request' || github.repository != 'fullstaq-ruby/server-edition' + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + include: + <%- contributor_distributions.each do |distro| -%> + <%- variants_for_ruby_version(rpv).each do |variant| -%> + - distro: '<%= distro[:name] %>' + variant: '<%= variant[:name] %>' + test_image: '<%= distro[:test_image] %>' + package_format: '<%= distro[:package_format] %>' + <%- end -%> + <%- end -%> + steps: + - uses: actions/checkout@v4 + + - name: Download packages + uses: actions/download-artifact@v4 + with: + name: contributor-packages + path: packages + + - name: Download utility Docker image + uses: actions/download-artifact@v4 + with: + name: '<%= docker_image_artifact_name('utility') %>' + path: docker-image-utility + - name: Load utility Docker image + run: ./internal-scripts/ci-cd/load-docker-image.sh + env: + TARBALL: docker-image-utility/image.tar.zst + + - name: Determine Ruby package filename + id: ruby_pkg + run: | + VARIANT="${{ matrix.variant }}" + DISTRO="${{ matrix.distro }}" + FORMAT="${{ matrix.package_format }}" + if [ "$VARIANT" = "normal" ]; then + VARIANT_SUFFIX="" + else + VARIANT_SUFFIX="-${VARIANT}" + fi + if [ "$FORMAT" = "DEB" ]; then + FILENAME="fullstaq-ruby-<%= rpv[:id] %>${VARIANT_SUFFIX}_<%= rpv[:package_revision] %>-${DISTRO}_amd64.deb" + else + SANITIZED_DISTRO=$(echo "$DISTRO" | tr -d '-') + FILENAME="fullstaq-ruby-<%= rpv[:id] %>${VARIANT_SUFFIX}-rev<%= rpv[:package_revision] %>-${SANITIZED_DISTRO}.x86_64.rpm" + fi + echo "filename=${FILENAME}" >> "$GITHUB_OUTPUT" + + - name: Test DEBs + if: matrix.package_format == 'DEB' + run: | + ./test-debs \ + -i '${{ matrix.test_image }}' \ + -v '${{ matrix.variant }}' \ + -r "$(pwd)/packages/${{ steps.ruby_pkg.outputs.filename }}" \ + -b "$(pwd)/packages/<%= rbenv_package_basename(:DEB) %>" \ + -c "$(pwd)/packages/<%= common_package_basename(:DEB) %>" + - name: Test RPMs + if: matrix.package_format == 'RPM' + run: | + ./test-rpms \ + -i '${{ matrix.test_image }}' \ + -v '${{ matrix.variant }}' \ + -r "$(pwd)/packages/${{ steps.ruby_pkg.outputs.filename }}" \ + -b "$(pwd)/packages/<%= rbenv_package_basename(:RPM) %>" \ + -c "$(pwd)/packages/<%= common_package_basename(:RPM) %>" diff --git a/.github/workflows/ci-cd-label-guard.yml b/.github/workflows/ci-cd-label-guard.yml new file mode 100644 index 0000000..dcf44fd --- /dev/null +++ b/.github/workflows/ci-cd-label-guard.yml @@ -0,0 +1,34 @@ +name: 'CI/CD: label guard' + +on: + pull_request_target: + types: [synchronize] + +jobs: + remove_ok_to_test: + name: Remove ok-to-test label on new push + runs-on: ubuntu-24.04 + permissions: + pull-requests: write + steps: + - name: Remove ok-to-test label if present + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const issue_number = context.payload.pull_request.number; + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number, + name: 'ok-to-test' + }); + console.log('Removed ok-to-test label'); + } catch (e) { + if (e.status === 404) { + console.log('Label ok-to-test not present, nothing to remove'); + } else { + throw e; + } + } diff --git a/.github/workflows/ci-cd-main.yml b/.github/workflows/ci-cd-main.yml index 14fe99e..832c4e4 100644 --- a/.github/workflows/ci-cd-main.yml +++ b/.github/workflows/ci-cd-main.yml @@ -22,6 +22,11 @@ on: paths-ignore: - '**.md' - 'dev-handbook/**' + pull_request_target: + types: [labeled] + paths-ignore: + - '**.md' + - 'dev-handbook/**' env: ## Set the following variable to a specific number to make the @@ -39,6 +44,10 @@ jobs: determine_necessary_jobs: name: Determine necessary jobs runs-on: ubuntu-24.04 + if: > + github.repository == 'fullstaq-ruby/server-edition' + && (github.event_name != 'pull_request_target' + || github.event.label.name == 'ok-to-test') environment: test permissions: id-token: write @@ -54,6 +63,8 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/fix/cicd-new-workflows' - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }} - uses: google-github-actions/auth@v2 with: project_id: ${{ vars.GCLOUD_PROJECT_ID }} @@ -83,6 +94,7 @@ jobs: check_workflow_uptodate: name: Check whether workflow is up-to-date runs-on: ubuntu-24.04 + if: github.repository == 'fullstaq-ruby/server-edition' steps: - uses: actions/checkout@v4 - name: Check diff --git a/.github/workflows/ci-cd-main.yml.erb b/.github/workflows/ci-cd-main.yml.erb index 85245e8..9f8ddaa 100644 --- a/.github/workflows/ci-cd-main.yml.erb +++ b/.github/workflows/ci-cd-main.yml.erb @@ -12,6 +12,11 @@ on: paths-ignore: - '**.md' - 'dev-handbook/**' + pull_request_target: + types: [labeled] + paths-ignore: + - '**.md' + - 'dev-handbook/**' env: ## Set the following variable to a specific number to make the @@ -29,6 +34,10 @@ jobs: determine_necessary_jobs: name: Determine necessary jobs runs-on: ubuntu-24.04 + if: > + github.repository == 'fullstaq-ruby/server-edition' + && (github.event_name != 'pull_request_target' + || github.event.label.name == 'ok-to-test') environment: test permissions: id-token: write @@ -44,6 +53,8 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/fix/cicd-new-workflows' - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.ref }} - uses: google-github-actions/auth@v2 with: project_id: ${{ vars.GCLOUD_PROJECT_ID }} @@ -73,6 +84,7 @@ jobs: check_workflow_uptodate: name: Check whether workflow is up-to-date runs-on: ubuntu-24.04 + if: github.repository == 'fullstaq-ruby/server-edition' steps: - uses: actions/checkout@v4 - name: Check diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a11344..88ec786 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,27 @@ Have a look at our [issue tracker](https://github.com/fullstaq-ruby/server-editi To learn how the Fullstaq Ruby Server Edition codebase works and how to develop it, please read our [development handbook](dev-handbook/README.md). +## Testing your changes + +### Automated CI on forks + +When you push to your fork or open a pull request, a contributor CI workflow runs automatically. It: + + * Validates CI/CD workflow YAML is up-to-date. + * Builds Ruby packages for two representative distributions (Ubuntu 24.04 and Enterprise Linux 9) with all three variants (normal, jemalloc, malloctrim). + * Runs smoke tests that install the packages and verify Ruby works correctly. + +No cloud credentials or special setup are needed — the workflow uses only Docker and GitHub Actions. + +If a maintainer wants to run the full CI pipeline against your PR (which tests all distributions and publishes to test repositories), they will add the `ok-to-test` label. This label is automatically removed when you push new commits, so the maintainer must re-review and re-label after each update. + +### Local builds and testing + +For faster iteration, you can build and test packages on your own machine. You only need Docker and Ruby >= 3.2: + + * **Building packages:** see [Building packages locally](dev-handbook/building-packages-locally.md) + * **Testing packages:** see [Testing packages locally](dev-handbook/testing-packages-locally.md) + ## Stuck? Need help? Please post something on our [discussion forum](https://github.com/fullstaq-ruby/server-edition/discussions). diff --git a/config.yml b/config.yml index 0689593..77ebd88 100644 --- a/config.yml +++ b/config.yml @@ -105,6 +105,13 @@ variant_exclusions: ## `package_revision` numbers too! jemalloc_version: '3.6.0' +## (Optional) +## Which distributions to include in the contributor CI workflow. +## This is a small subset used for fast feedback on forks. +contributor_distributions: + - ubuntu-24.04 + - el-9 + ## (Required) ## Specify which distributions to build packages for. ## When set to 'all', will build for all supported distributions. diff --git a/container-entrypoints/test-rpms-prepare b/container-entrypoints/test-rpms-prepare index 7b32b12..be92890 100755 --- a/container-entrypoints/test-rpms-prepare +++ b/container-entrypoints/test-rpms-prepare @@ -14,4 +14,4 @@ require_container_mount "$OUTPUT_PATH" run cp /input/* /output/ -run createrepo /output +run createrepo_c /output diff --git a/dev-handbook/building-packages-locally.md b/dev-handbook/building-packages-locally.md index 62c12b3..8ef60a9 100644 --- a/dev-handbook/building-packages-locally.md +++ b/dev-handbook/building-packages-locally.md @@ -1,5 +1,7 @@ # Building packages locally +> **Tip:** If you just want to validate that your changes compile and pass tests, the contributor CI workflow does this automatically when you push to your fork. See [CONTRIBUTING.md](../CONTRIBUTING.md#testing-your-changes) for details. The instructions below are for local builds when you want faster iteration or need to debug packaging issues. + This tutorial shows how you can build packages on your own computer. Because we follow [the "minimal dependencies" principle](minimal-dependencies-principle.md), you can build packages for any distribution, regardless of which OS or distribution you're running on. diff --git a/internal-scripts/generate-ci-cd-yaml.rb b/internal-scripts/generate-ci-cd-yaml.rb index db4f87c..e8ef5a0 100755 --- a/internal-scripts/generate-ci-cd-yaml.rb +++ b/internal-scripts/generate-ci-cd-yaml.rb @@ -35,6 +35,7 @@ def main end generate_yaml_file_from_template(template_name: 'ci-cd-publish-test-test') generate_yaml_file_from_template(template_name: 'ci-cd-publish-test-production') + generate_yaml_file_from_template(template_name: 'ci-cd-contributor') end private diff --git a/internal-scripts/test-debs b/internal-scripts/test-debs index 3e07aa4..edbf41d 100755 --- a/internal-scripts/test-debs +++ b/internal-scripts/test-debs @@ -9,7 +9,7 @@ source "$SELFDIR/../lib/library.sh" header "Installing packages" -ESSENTIAL_PACKAGES=(perl sudo binutils) +ESSENTIAL_PACKAGES=(perl sudo binutils adduser) if [[ "$SERVER" = "" ]]; then echo "+ Create /etc/apt/sources.list.d/local.list" diff --git a/lib/ci_workflow_support.rb b/lib/ci_workflow_support.rb index 5255440..a8fa265 100644 --- a/lib/ci_workflow_support.rb +++ b/lib/ci_workflow_support.rb @@ -76,6 +76,20 @@ def distributions end end + def contributor_distributions + @contributor_distributions ||= begin + names = config[:contributor_distributions] + return [] if names.nil? + names.map do |name| + { + name: name, + package_format: autodetect_package_format(name), + test_image: determine_test_image_for(name), + } + end + end + end + def distribution_buckets @distribution_buckets ||= GeneralSupport.bucketize(distributions, DISTRIBUTIONS_BUCKETS_MAX_NUM) @@ -261,6 +275,10 @@ def ruby_package_versions end end + def latest_ruby_package_version + ruby_package_versions.first + end + def ruby_package_versions_for_distro(distro) result = ruby_package_versions.find_all do |ruby_package_version| !ruby_package_version_excluded_from_distro?(ruby_package_version, distro)