From 023514e26cc4a1045fc352486ab3ccfabd3fbf07 Mon Sep 17 00:00:00 2001 From: Nikita Belonogov Date: Wed, 16 Oct 2024 15:05:37 +0400 Subject: [PATCH] ci: PLT-527: Add SDK Follow Merge --- .../follow-merge-upstream-repo-sync.yml | 304 ++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 .github/workflows/follow-merge-upstream-repo-sync.yml diff --git a/.github/workflows/follow-merge-upstream-repo-sync.yml b/.github/workflows/follow-merge-upstream-repo-sync.yml new file mode 100644 index 00000000..42f2414b --- /dev/null +++ b/.github/workflows/follow-merge-upstream-repo-sync.yml @@ -0,0 +1,304 @@ +name: 'Follow Merge: Upstream repo sync' + +on: + repository_dispatch: + types: + - upstream_repo_update + +concurrency: + group: ${{ github.workflow }}-${{ github.event.client_payload.branch_name }} + +env: + RELEASE_BRANCH_PREFIX: "lse-release/" + NODE: "18" + YARN: "1.22" + UPSTREAM_REPO_WORKDIR: "upstream" + +jobs: + open: + name: Sync PR + if: | + github.event.client_payload.event_action == 'opened' || + github.event.client_payload.event_action == 'synchronize' || + github.event.client_payload.event_action == 'merged' + runs-on: ubuntu-22.04 + steps: + - uses: hmarr/debug-action@v3.0.0 + + - name: Details + id: details + shell: bash + env: + REPO_NAME: "${{ github.event.client_payload.repo_name }}" + run: | + set -xeuo pipefail + + case "${REPO_NAME}" in + */label-studio-sdk) + echo "poetry=true" >> $GITHUB_OUTPUT + echo "poetry_group=default" >> $GITHUB_OUTPUT + ;; + *) + echo "::error::Repository ${REPO_NAME} is not supported" + exit 1 + ;; + esac + + - name: Checkout Actions Hub + uses: actions/checkout@v4 + with: + token: ${{ secrets.GIT_PAT }} + repository: HumanSignal/actions-hub + path: ./.github/actions-hub + + - name: Parse Follow Merge dispatch event payload + uses: ./.github/actions-hub/actions/follow-merge-parse-payload + id: fm + + - name: Find or Create branch + uses: ./.github/actions-hub/actions/github-find-or-create-branch + id: get-branch + with: + github_token: ${{ secrets.GIT_PAT }} + branch_name: "${{ steps.fm.outputs.branch_name }}" + + - name: Checkout repo + uses: actions/checkout@v4 + if: steps.fm.outputs.repo_name && steps.fm.outputs.branch_name + with: + token: ${{ secrets.GIT_PAT }} + fetch-depth: 0 + ref: ${{ steps.get-branch.outputs.branch_name }} + path: "${{ env.UPSTREAM_REPO_WORKDIR }}" + + - name: Git Configure + uses: ./.github/actions-hub/actions/git-configure + with: + username: ${{ steps.fm.outputs.author_username }} + email: ${{ steps.fm.outputs.author_email }} + + - name: Git Merge + id: merge + continue-on-error: true + uses: ./.github/actions-hub/actions/git-merge + with: + base_branch: ${{ steps.get-branch.outputs.base_name }} + head_branch: ${{ steps.get-branch.outputs.branch_name }} + our_files: "pyproject.toml poetry.lock web/package.json web/yarn.lock" + working_directory: "${{ env.UPSTREAM_REPO_WORKDIR }}" + + - name: "Poetry: Set up" + if: steps.details.outputs.poetry + uses: Gr1N/setup-poetry@v9 + + - name: Commit submodule + shell: bash + working-directory: "${{ env.UPSTREAM_REPO_WORKDIR }}" + run: | + set -xeuo pipefail + + poetry add "https://github.com/${{ steps.fm.outputs.repo_name }}/archive/${{ steps.fm.outputs.commit_sha }}.zip" --lock + + git diff + git add -A + git status -s + git commit --allow-empty -m '[submodules] Bump ${{ steps.fm.outputs.repo_name }} version' -m 'Workflow run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + + - name: Update Poetry Lock File + continue-on-error: true + working-directory: "${{ env.UPSTREAM_REPO_WORKDIR }}" + run: | + set -xeuo pipefail + + commit_message="Update Poetry lock file" + commit_message_workflow_link='Workflow run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}' + + poetry lock --no-update + + git add poetry.lock + git commit -m "${commit_message}" -m "${commit_message_workflow_link}" + + - name: Git Push + uses: ./.github/actions-hub/actions/git-push + with: + working_directory: "${{ env.UPSTREAM_REPO_WORKDIR }}" + + - name: Find or Create PR + uses: ./.github/actions-hub/actions/github-find-or-create-pull-request + id: get-pr + with: + github_token: ${{ secrets.GIT_PAT }} + branch_name: "${{ steps.get-branch.outputs.branch_name }}" + title: "${{ steps.fm.outputs.title }}" + description: | + Hi @${{ steps.fm.outputs.actor }}! + + This PR was automaticaly generated via Follow Merge. + Please ensure that all linked upstream Pull Requests are merged before proceeding with this one. + + - name: Add PR Reviewers + uses: ./.github/actions-hub/actions/github-add-pull-request-reviewers + continue-on-error: true + with: + github_token: ${{ secrets.GIT_PAT }} + pullrequest_number: "${{ steps.get-pr.outputs.number }}" + reviewers: "${{ steps.fm.outputs.actor }}" + + - name: Link PR + uses: ./.github/actions-hub/actions/github-link-upstream-pull-request + continue-on-error: true + with: + github_token: ${{ secrets.GIT_PAT }} + pullrequest_number: "${{ steps.get-pr.outputs.number }}" + upstream_pullrequest_link: "${{ steps.fm.outputs.pr_html_url }}" + + + - name: Convert to ready for review + if: github.event.client_payload.event_action == 'merged' + id: ready-for-review-pr + shell: bash + env: + GIT_PAT: ${{ secrets.GIT_PAT }} + run: | + echo "$GIT_PAT" | gh auth login --with-token + gh api graphql -F id='${{ steps.get-pr.outputs.node_id }}' -f query=' + mutation($id: ID!) { + markPullRequestReadyForReview(input: { pullRequestId: $id }) { + pullRequest { + id + } + } + } + ' + + - name: Enable AutoMerge + id: enable-pr-automerge + if: github.event.client_payload.event_action == 'merged' + shell: bash + env: + GIT_PAT: ${{ secrets.GIT_PAT }} + run: | + echo "$GIT_PAT" | gh auth login --with-token + gh api graphql -f pull='${{ steps.get-pr.outputs.node_id }}' -f query=' + mutation($pull: ID!) { + enablePullRequestAutoMerge(input: {pullRequestId: $pull, mergeMethod: SQUASH}) { + pullRequest { + id + number + } + } + }' + + - name: Notify on failure + uses: ./.github/actions-hub/actions/github-create-comment + if: failure() + with: + github_token: ${{ secrets.GIT_PAT }} + repository: "${{ steps.fm.outputs.repo_name }}" + issue_number: "${{ steps.fm.outputs.pr_number }}" + body: | + Follow Merge downstream workflow has been failed. + > [Workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + + + others: + name: Other actions with PR + if: | + github.event.client_payload.event_action == 'converted_to_draft' || + github.event.client_payload.event_action == 'ready_for_review' || + github.event.client_payload.event_action == 'closed' + runs-on: ubuntu-latest + steps: + - uses: hmarr/debug-action@v3.0.0 + + - name: Get PR + uses: actions/github-script@v7 + id: get-pr + with: + github-token: ${{ secrets.GIT_PAT }} + script: | + const {repo, owner} = context.repo; + const branchName = '${{ github.event.client_payload.branch_name }}'; + const branchNameLowerCase = branchName.toLowerCase(); + const {data: listPullsResponse} = await github.rest.pulls.list({ + owner, + repo, + head: `${owner}:${branchName}`, + per_page: 1 + }); + const {data: listPullsResponseLowerCase} = await github.rest.pulls.list({ + owner, + repo, + head: `${owner}:${branchNameLowerCase}`, + per_page: 1 + }); + + if (listPullsResponse.length !== 0) { + console.log(`Found PR for branch '${branchName}'`) + core.setOutput("branch-name", branchName); + return listPullsResponse + } else if (listPullsResponseLowerCase.length !== 0) { + console.log(`Found PR for branch '${branchNameLowerCase}'`) + core.setOutput("branch-name", branchNameLowerCase); + return listPullsResponseLowerCase + } else { + console.log(`PR for branch '${branchNameLowerCase}' is not created yet`) + core.setOutput("branch-name", branchNameLowerCase); + return listPullsResponseLowerCase + } + + - name: Close PR + if: github.event.client_payload.event_action == 'closed' + id: close-pr + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GIT_PAT }} + script: | + const { repo, owner } = context.repo; + const listPullsResponse = ${{ steps.get-pr.outputs.result }} + for (let pr of listPullsResponse ) { + core.info(`Closing ${ pr.html_url }`) + github.rest.pulls.update({ + owner, + repo, + pull_number: pr.number, + state: 'close' + }); + } + + - name: Convert to draft + if: github.event.client_payload.event_action == 'converted_to_draft' + id: convert-pr-to-draft + shell: bash + env: + GIT_PAT: ${{ secrets.GIT_PAT }} + run: | + echo "$GIT_PAT" | gh auth login --with-token + gh api graphql -F id='${{ fromJson(steps.get-pr.outputs.result)[0].node_id }}' -f query=' + mutation($id: ID!) { + convertPullRequestToDraft(input: { pullRequestId: $id }) { + pullRequest { + id + isDraft + } + } + } + ' + + - name: Convert to ready for review + if: github.event.client_payload.event_action == 'ready_for_review' + id: ready-for-review-pr + shell: bash + env: + GIT_PAT: ${{ secrets.GIT_PAT }} + run: | + echo "$GIT_PAT" | gh auth login --with-token + gh api graphql -F id='${{ fromJson(steps.get-pr.outputs.result)[0].node_id }}' -f query=' + mutation($id: ID!) { + markPullRequestReadyForReview(input: { pullRequestId: $id }) { + pullRequest { + id + } + } + } + '