diff --git a/.github/workflows/auto_bump_environment_deps.yaml b/.github/workflows/auto_bump_environment_deps.yaml new file mode 100644 index 0000000000..df24226f61 --- /dev/null +++ b/.github/workflows/auto_bump_environment_deps.yaml @@ -0,0 +1,216 @@ +name: Auto Bump Environment Deps + +on: + workflow_dispatch: + inputs: + auto_merge: + description: "Enable auto-merge for the generated PR" + required: true + type: boolean + default: true + repository_dispatch: + types: + - environment-deps-updated + - verifiers-updated + - renderers-updated + - research-environments-updated + schedule: + - cron: "17 */4 * * *" + +concurrency: + group: auto-bump-environment-deps + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + +env: + BASE_BRANCH: main + BUMP_BRANCH: chore/bump-environment-deps + +jobs: + bump: + name: Bump submodules + runs-on: ubuntu-latest + steps: + - name: Check bot token + env: + AUTO_BUMP_TOKEN: ${{ secrets.AUTO_BUMP_TOKEN }} + run: | + if [ -z "$AUTO_BUMP_TOKEN" ]; then + echo "::error title=Missing AUTO_BUMP_TOKEN::Set AUTO_BUMP_TOKEN to a PAT or GitHub App token that can push branches, open PRs, and trigger PR workflows." + exit 1 + fi + + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ env.BASE_BRANCH }} + fetch-depth: 0 + submodules: false + token: ${{ secrets.AUTO_BUMP_TOKEN }} + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "uv.lock" + + - name: Configure git + env: + AUTO_BUMP_TOKEN: ${{ secrets.AUTO_BUMP_TOKEN }} + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git config --global url."https://x-access-token:${AUTO_BUMP_TOKEN}@github.com/".insteadOf "git@github.com:" + git config --global url."https://x-access-token:${AUTO_BUMP_TOKEN}@github.com/".insteadOf "https://github.com/" + + - name: Update dependency submodules + id: bump + run: | + set -euo pipefail + + submodules=( + deps/verifiers + deps/renderers + deps/research-environments + ) + init_submodules=( + "${submodules[@]}" + deps/pydantic-config + ) + + git submodule sync --recursive -- "${init_submodules[@]}" + git submodule update --init --recursive --depth 1 -- "${init_submodules[@]}" + + git checkout -B "$BUMP_BRANCH" + git submodule update --remote --recursive -- "${submodules[@]}" + + summary_file=/tmp/environment-deps-summary.md + : > "$summary_file" + + for submodule_path in "${submodules[@]}"; do + before="$(git ls-tree HEAD "$submodule_path" | awk '{print $3}')" + after="$(git -C "$submodule_path" rev-parse HEAD)" + + case "$submodule_path" in + deps/verifiers) + repo_url="https://github.com/PrimeIntellect-ai/verifiers" + ;; + deps/renderers) + repo_url="https://github.com/PrimeIntellect-ai/renderers" + ;; + deps/research-environments) + repo_url="https://github.com/PrimeIntellect-ai/research-environments" + ;; + esac + + if [ "$before" != "$after" ]; then + printf -- "- \`%s\`: [\`%s\`...\`%s\`](%s/compare/%s...%s)\n" \ + "$submodule_path" "${before:0:7}" "${after:0:7}" "$repo_url" "$before" "$after" \ + >> "$summary_file" + fi + done + + if [ ! -s "$summary_file" ]; then + echo "has_changes=false" >> "$GITHUB_OUTPUT" + echo "No dependency submodule updates found." + exit 0 + fi + + echo "has_changes=true" >> "$GITHUB_OUTPUT" + { + echo "summary<> "$GITHUB_OUTPUT" + + - name: Refresh lockfile + if: steps.bump.outputs.has_changes == 'true' + run: uv lock + + - name: Validate lockfile + if: steps.bump.outputs.has_changes == 'true' + run: uv sync --all-extras --locked --dry-run + + - name: Commit and push update + if: steps.bump.outputs.has_changes == 'true' + id: commit + run: | + set -euo pipefail + + git fetch origin "refs/heads/${BUMP_BRANCH}:refs/remotes/origin/${BUMP_BRANCH}" 2>/dev/null || true + + if git rev-parse --verify --quiet "refs/remotes/origin/${BUMP_BRANCH}" >/dev/null; then + if git diff --quiet "origin/${BUMP_BRANCH}" -- deps/verifiers deps/renderers deps/research-environments uv.lock; then + echo "Remote bump branch already contains this update." + echo "sha=$(git rev-parse origin/${BUMP_BRANCH})" >> "$GITHUB_OUTPUT" + echo "pushed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + fi + + git add deps/verifiers deps/renderers deps/research-environments uv.lock + git commit -m "chore: bump environment deps" + git push --force-with-lease origin "HEAD:${BUMP_BRANCH}" + + echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + echo "pushed=true" >> "$GITHUB_OUTPUT" + + - name: Create or update pull request + if: steps.bump.outputs.has_changes == 'true' + id: pr + env: + GH_TOKEN: ${{ secrets.AUTO_BUMP_TOKEN }} + SUBMODULE_SUMMARY: ${{ steps.bump.outputs.summary }} + run: | + set -euo pipefail + + body_file=/tmp/environment-deps-pr.md + cat > "$body_file" <> "$GITHUB_OUTPUT" + + - name: Enable auto-merge + if: steps.bump.outputs.has_changes == 'true' && (github.event_name != 'workflow_dispatch' || inputs.auto_merge) + env: + GH_TOKEN: ${{ secrets.AUTO_BUMP_TOKEN }} + run: | + if [ "$(gh pr view "${{ steps.pr.outputs.number }}" --json autoMergeRequest --jq '.autoMergeRequest != null')" = "true" ]; then + echo "Auto-merge is already enabled." + exit 0 + fi + + gh pr merge "${{ steps.pr.outputs.number }}" \ + --auto \ + --squash \ + --delete-branch \ + --match-head-commit "${{ steps.commit.outputs.sha }}" diff --git a/docs/development.md b/docs/development.md index 253c36fb29..90ffe803f9 100644 --- a/docs/development.md +++ b/docs/development.md @@ -43,9 +43,12 @@ uv run pytest tests/integration/test_reverse_text.py -vvs # one specific scenar | [`cpu_tests.yaml`](https://github.com/PrimeIntellect-ai/prime-rl/blob/main/.github/workflows/cpu_tests.yaml) | every PR + push to `main` | `pytest tests/unit -m "not gpu"`, plus a slim-wheel install check that `prime-rl-configs` imports cleanly without heavy deps (no torch / vllm / transformers / wandb / verifiers / datasets / liger / loguru in `sys.modules`) | `ubuntu-latest` | | [`gpu_tests.yaml`](https://github.com/PrimeIntellect-ai/prime-rl/blob/main/.github/workflows/gpu_tests.yaml) | every non-draft PR + push to `main` | `pytest tests/unit -m gpu`, plus a matrix of named integration scenarios (`reverse_text`, `reverse_text_sft`, `reverse_text_lora`, `reverse_text_moe`, `reverse_text_multi_run`, `reverse_text_rl_opd`, `reverse_text_rl_sft`, `reverse_text_sft_lora`, `alphabet_sort`, `benchmark_regression`) | self-hosted GPU runners (`vm`, `4xa6000`) | | [`nightly_tests.yaml`](https://github.com/PrimeIntellect-ai/prime-rl/blob/main/.github/workflows/nightly_tests.yaml) | 03:00 PST daily + manual `workflow_dispatch` (single-file filter optional) | every file in `tests/nightly/`, one matrix job per file | `research-cluster` | +| [`auto_bump_environment_deps.yaml`](https://github.com/PrimeIntellect-ai/prime-rl/blob/main/.github/workflows/auto_bump_environment_deps.yaml) | every 4 hours + manual `workflow_dispatch` + upstream `repository_dispatch` | bumps `deps/verifiers`, `deps/renderers`, and `deps/research-environments`, refreshes `uv.lock`, opens a non-draft PR, and enables auto-merge | `ubuntu-latest` | The GPU + Nightly workflows skip drafts — open the PR as **Draft** until you're ready to consume CI compute, then mark it ready for review to trigger the GPU matrix. +The auto-bump workflow requires an `AUTO_BUMP_TOKEN` secret from a PAT or GitHub App installation that can push branches and open PRs. Use a real bot token rather than `GITHUB_TOKEN` so the generated PR triggers the normal PR workflows before GitHub auto-merge merges it. + ### Markers Two pytest markers are declared in `pyproject.toml` (`addopts = "--strict-markers"`):