diff --git a/.github/workflows/ifu.yml b/.github/workflows/ifu.yml new file mode 100644 index 0000000000000..92ae195b96702 --- /dev/null +++ b/.github/workflows/ifu.yml @@ -0,0 +1,119 @@ +name: Sync with upstream + +on: + workflow_dispatch: {} + schedule: + # Runs every 14 days at 09:00 AM UTC/ 04:00 AM CST + - cron: "0 9 */14 * *" + +permissions: + contents: write # push branches/tags + pull-requests: write # create PRs + +concurrency: + group: ifu + # If two jobs are running simultaneously, we will queue them (not cancel the one running) + cancel-in-progress: false + +jobs: + ifu-workflow: + runs-on: ubuntu-latest + env: + # Configuration you described + UPSTREAM_REMOTE: upstream # upstream remote name (pytorch/pytorch) + UPSTREAM_BRANCH: main # pytorch/pytorch main + ROCM_REMOTE: origin # this repo (fork); actions/checkout sets this to origin + ROCM_BRANCH: rocm7.1_internal_testing + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # used by gh; provided by Actions + steps: + - name: Checkout ROCm fork (full history) + uses: actions/checkout@v4 + with: + fetch-depth: 0 # need full history for merges/tags + submodules: recursive + + - name: Add upstream remote (pytorch/pytorch) + run: | + if ! git remote get-url upstream >/dev/null 2>&1; then + git remote add upstream https://github.com/pytorch/pytorch.git + fi + # Confirm remotes + git remote -v + + - name: Configure Git user + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Fetch upstream and local branch + run: | + git fetch $UPSTREAM_REMOTE $UPSTREAM_BRANCH + git fetch $ROCM_REMOTE $ROCM_BRANCH + + - name: Compute date tag and create working branch + id: tag + shell: bash + run: | + DATE="$(date +"%Y-%m-%d")" + TAG="${ROCM_BRANCH}_IFU_${DATE}" + echo "TAG=${TAG}" >> $GITHUB_OUTPUT + # Start from rocm branch + git checkout -b "$TAG" "${ROCM_REMOTE}/${ROCM_BRANCH}" + git status + + - name: Create pre-merge tag + run: | + git tag "${{ steps.tag.outputs.TAG }}_pre" + + - name: Merge upstream into working branch (non-interactive) + id: merge + run: | + if git merge "upstream/${UPSTREAM_BRANCH}" --no-edit; then + echo "merge_status=clean" >> $GITHUB_OUTPUT + else + echo "Merge conflicts detected. Committing current resolution snapshot." + git status + git add -A + git commit --no-edit + echo "merge_status=conflicted" >> $GITHUB_OUTPUT + fi + + - name: Post-merge submodule sync & pin + run: | + # Keep submodules consistent with the committed gitlinks + git submodule sync + git submodule update --init --recursive + + - name: Push branch & tag to fork + run: | + git push ${ROCM_REMOTE} "${{ steps.tag.outputs.TAG }}" + git push ${ROCM_REMOTE} "${{ steps.tag.outputs.TAG }}_pre" || true + + - name: Authenticate gh (non-interactive) + env: + GH_TOKEN: ${{ env.GH_TOKEN }} + run: | + # The GitHub-hosted runner has gh preinstalled. + gh auth status || echo "$GH_TOKEN" | gh auth login --with-token + gh repo set-default "${{ github.repository }}" + + - name: Create Pull Request with gh + env: + GH_TOKEN: ${{ env.GH_TOKEN }} + run: | + BASE="${ROCM_BRANCH}" + HEAD="${{ steps.tag.outputs.TAG }}" + TITLE="[AUTOGENERATED] $HEAD" + BODY="Merged latest changes from ${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH} into ${ROCM_BRANCH} on $(date -u +'%Y-%m-%d')" + + # If a PR for this head already exists, skip creating a new one + if gh pr list --head "$HEAD" --base "$BASE" --state all --json number | grep -q '[0-9]'; then + echo "PR already exists for $HEAD -> $BASE. Skipping creation." + else + gh pr create --base "$BASE" --head "$HEAD" --title "$TITLE" --body "$BODY" + fi + + - name: Summarize + run: | + echo "::notice title=IFU Completed::Branch ${{ steps.tag.outputs.TAG }} pushed. PR created (or already existed)." +