diff --git a/.github/workflows/create-gotoprod-pr.yml b/.github/workflows/create-gotoprod-pr.yml new file mode 100644 index 0000000..f615b02 --- /dev/null +++ b/.github/workflows/create-gotoprod-pr.yml @@ -0,0 +1,147 @@ +name: Create Go-To-Prod Pull Request + +on: + workflow_call: + inputs: + base: + description: "Base branch for the pull request" + type: string + required: false + default: "main" + +jobs: + create_pr: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Create Pull Request + uses: actions/github-script@v7 + with: + script: | + const title = ':rocket: Go to Production'; + const head = '${{ github.ref_name }}'; + const base = '${{ inputs.base }}'; + async function handlePR(existingPRs) { + let prNumber; + if (existingPRs.data.length > 0) { + const existingPR = existingPRs.data[0]; + prNumber = existingPR.number; + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + title: title + }); + } else { + const result = await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + head: head, + base: base + }); + prNumber = result.data.number; + } + return prNumber; + } + + async function fetchAndAddReviewers(prNumber) { + const commits = await github.rest.pulls.listCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber + }); + const contributors = commits.data + .map(commit => commit.author.login) + .filter(username => !username.includes('[bot]')); + const uniqueContributors = [...new Set(contributors)]; + await github.rest.pulls.requestReviewers({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + reviewers: uniqueContributors + }); + return uniqueContributors; + } + + try { + const existingPRs = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + head: head, + base: base + }); + const prNumber = await handlePR(existingPRs); + let contributors = await fetchAndAddReviewers(prNumber); + + // Add reviewers + await github.rest.pulls.requestReviewers({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + reviewers: contributors + }); + const bodyParts = [ + '## :rocket: Automated PR to prepare Go-To-Production', + `**Branch**: \`${{ github.ref_name }}\``, + `**Base**: \`${{ inputs.base }}\``, + '### :mag_right: Changes', + '### :busts_in_silhouette: Contributors', + '- ' + contributors.map(c => '@' + c).join('\n- ') + ]; + + // Fetch list of changes (diffs) + const diffs = await github.rest.repos.compareCommits({ + owner: context.repo.owner, + repo: context.repo.repo, + base: base, + head: head + }); + const mergedPRs = []; + const Commits = []; + diffs.data.commits.forEach(commit => { + const firstLine = commit.commit.message.split('\n')[0]; + if (commit.parents.length > 1) { + mergedPRs.push(`- ${firstLine}`); + } else { + Commits.push(`- ${firstLine}`); + } + }); + const changes = [ + '#### :twisted_rightwards_arrows: Merged Pull Requests', + mergedPRs.join('\n'), + '#### :memo: Commits', + Commits.join('\n') + ].join('\n\n'); + bodyParts.splice(4, 0, changes); + + const updatedBody = bodyParts.join('\n\n'); + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + body: updatedBody + }); + + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + labels: ['go-to-prod', ':robot: automated-pr'] + }); + github.rest.issues.updateLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: 'go-to-prod', + color: 'ff7f00' + }); + } catch (error) { + console.error('Failed to create or update PR:', error); + } \ No newline at end of file diff --git a/workflow-templates/gotoprod-pr.properties.json b/workflow-templates/gotoprod-pr.properties.json new file mode 100644 index 0000000..9e5243f --- /dev/null +++ b/workflow-templates/gotoprod-pr.properties.json @@ -0,0 +1,10 @@ +{ + "name": "Go-To-Prod PR", + "description": "Go-To-Prod PR workflow template.", + "iconName": "octicon goal", + "categories": [ + "Automation", + "deployment", + "utilities" + ] +} \ No newline at end of file diff --git a/workflow-templates/gotoprod-pr.yaml b/workflow-templates/gotoprod-pr.yaml new file mode 100644 index 0000000..699779f --- /dev/null +++ b/workflow-templates/gotoprod-pr.yaml @@ -0,0 +1,10 @@ +name: Go-To-Prod PR + +on: + push: + branches: + - $default-branch + +jobs: + call-gotoprod-pr-workflow: + uses: ZeroGachis/.github/.github/workflows/create-gotoprod-pr.yml@v4