This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Create Branches and PRs on assign | |
permissions: | |
contents: write | |
issues: write | |
pull-requests: write | |
repository-projects: write | |
statuses: write | |
on: | |
issues: | |
types: [assigned] | |
jobs: | |
generate-branchs-path: | |
outputs: | |
payloads: ${{ steps.generate-branches.outputs.result }} | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/github-script@v7 | |
name: Get parent issues | |
id: get-parent-issues | |
with: | |
script: | | |
let _issueTrakedTemplate = ` | |
trackedInIssues(first: 1) { | |
nodes { | |
title | |
number | |
labels(first: 20) { | |
nodes { | |
name | |
} | |
} | |
#CHILD | |
} | |
}`; | |
function createTrackedIssuesReq(recurse) { | |
let query = `query Nodes($number: Int!, $repo: String!, $organization: String!) { | |
organization(login: $organization) { | |
repository(name: $repo) { | |
issue(number: $number) { | |
title | |
number | |
labels(first: 20) { | |
nodes { | |
name | |
} | |
} | |
#CHILD | |
} | |
} | |
} | |
}`; | |
do { | |
query = query.replace("#CHILD", _issueTrakedTemplate) | |
} while (recurse--); | |
return query.replace("#CHILD", ""); | |
} | |
let query = createTrackedIssuesReq(6); | |
console.log("query", query) | |
const variables = { | |
number: parseInt(${{ github.event.issue.number }}, 10), | |
repo: "${{ github.event.repository.name }}", | |
organization: "${{ github.event.repository.owner.login }}" | |
} | |
const result = await github.graphql(query, variables); | |
console.log(JSON.stringify(result)) | |
return result.organization.repository.issue; | |
- uses: actions/github-script@v7 | |
name: Build ancestor array | |
id: build-ancestor-array | |
with: | |
script: | | |
const ancestors = [] | |
const node = ${{ steps.get-parent-issues.outputs.result }} | |
let current = node?.trackedInIssues?.nodes[0] | |
for (; current; current = current?.trackedInIssues?.nodes[0]) { | |
ancestors.push(current) | |
} | |
ancestors.reverse() | |
console.log(ancestors) | |
return ancestors | |
- name: get branch prefix | |
id: get-branch-prefix | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const ancestors = JSON.parse(${{ toJson(steps.build-ancestor-array.outputs.result) }}); | |
console.error(ancestors) | |
const issueLabels = JSON.parse(`${{ toJson(github.event.issue.labels) }}`); | |
console.error(issueLabels) | |
const labels = ancestors.length > 0 ? ancestors[0].labels.nodes : issueLabels; | |
console.error(labels) | |
const isUserStory = labels.some((label) => label.name === "user story") | |
console.error(isUserStory) | |
const isBug = labels.some((label) => label.name === "bug") | |
console.error(isBug) | |
const isTask = labels.some((label) => label.name === "task") | |
console.error(isTask) | |
const isTechnicalStory = labels.some((label) => label.name === "technical story") | |
console.error(isTechnicalStory) | |
if (isUserStory && !isTechnicalStory) { | |
console.error('feat/') | |
return 'feat/' | |
} else if (isTechnicalStory) { | |
console.error('chore/') | |
return 'chore/' | |
} else if (isBug) { | |
console.error('bug/') | |
return 'bug/' | |
} else if (isTask) { | |
console.error('task/') | |
return '' | |
} else { | |
console.error('No type found') | |
throw new Error("No type found") | |
} | |
- name: generate branches | |
id: generate-branches | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
function _sanitizeBranchName(title) { | |
return title.replace(/[^a-zA-Z0-9-]/g, '-').replace(/-{2,}/g, "-").replace(/-+$/, "").toLowerCase() | |
} | |
const ancestors = JSON.parse(`${{ steps.build-ancestor-array.outputs.result }}`) | |
const rootBranchPrefix = ${{ steps.get-branch-prefix.outputs.result }} | |
const firstIssueNumber = ancestors.length > 0 ? ancestors[0].number : ${{ github.event.issue.number }} | |
const firstBranchName = rootBranchPrefix | |
+ firstIssueNumber.toString() | |
+ '-' | |
+ _sanitizeBranchName(ancestors.length > 0 ? ancestors[0].title : "${{ github.event.issue.title }}") | |
+ '-staging' | |
const payloads = [ | |
{ | |
baseBranch: 'dev', | |
headBranch: firstBranchName, | |
prTitle: `${firstIssueNumber} - ${ancestors.length > 0 ? ancestors[0].title : "${{ github.event.issue.title }}"}`, | |
issueNumber: firstIssueNumber | |
} | |
] | |
ancestors.slice(1).forEach((issue, index) => { | |
payloads.push({ | |
baseBranch: payloads[index].headBranch, | |
headBranch: payloads[index].headBranch.replace(/-staging$/, '') | |
+ '/' | |
+ issue.number.toString() | |
+ '-' | |
+ _sanitizeBranchName(issue.title) | |
+ '-staging', | |
prTitle: `${issue.number} - ${issue.title}`, | |
issueNumber: issue.number | |
}) | |
}) | |
if (ancestors.length > 0) { | |
payloads.push({ | |
baseBranch: payloads[payloads.length - 1].headBranch, | |
headBranch: payloads[payloads.length - 1].headBranch.replace(/-staging$/, '') | |
+ '/' | |
+ (${{ github.event.issue.number }}).toString() | |
+ '-' | |
+ _sanitizeBranchName("${{ github.event.issue.title }}") | |
+ '-staging', | |
prTitle: `${{ github.event.issue.number }} - ${{ github.event.issue.title }}`, | |
issueNumber: ${{ github.event.issue.number }} | |
}) | |
} | |
return payloads | |
create-branch-and-draft: | |
runs-on: ubuntu-latest | |
needs: generate-branchs-path | |
strategy: | |
matrix: | |
payload: ${{ fromJson(needs.generate-branchs-path.outputs.payloads) }} | |
max-parallel: 1 | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Check if branch exists | |
id: check-branch-exists | |
continue-on-error: true | |
# should check if branch exists and set branchExists=true if it does, otherwise branchExists=false | |
run: | | |
git fetch --all | |
git checkout ${{ matrix.payload.headBranch }} | |
echo "branchExists=true" >> $GITHUB_OUTPUT | |
echo "Branch exists" | |
- name: Generate UUID | |
id: generate-uuid | |
run: | | |
echo "uuid=$(cat /proc/sys/kernel/random/uuid | sed 's/[-]//g' | head -c 20)" >> $GITHUB_OUTPUT | |
- name: Create branch | |
id: create-branch | |
# if branch does not exist, create it | |
if: steps.check-branch-exists.outputs.branchExists != 'true' | |
run: | | |
git checkout ${{ matrix.payload.baseBranch }} | |
git checkout -b ${{ matrix.payload.headBranch }} | |
git config --global user.email "ci@astrodevslabs.io" && git config --global user.name "Astrodevs CI" | |
echo "${{ env.REMOVE_UUID }}" > remove-me-${{ env.REMOVE_UUID }}.txt | |
git add remove-me-${{ env.REMOVE_UUID }}.txt | |
git commit -m "chore: create branch ${{ matrix.payload.headBranch }}" | |
git push origin ${{ matrix.payload.headBranch }} | |
env: | |
REMOVE_UUID: ${{ steps.generate-uuid.outputs.uuid }} | |
- name: Create pull request | |
continue-on-error: true | |
env: | |
GH_TOKEN: ${{ github.token }} | |
run: | | |
gh pr create --title "${{ matrix.payload.prTitle }}" --body "Solves #${{ matrix.payload.issueNumber }}" --base ${{matrix.payload.baseBranch }} --head ${{matrix.payload.headBranch }} --repo ${{ github.event.repository.full_name }} --draft |