Skip to content

chore(deps-dev): update setuptools requirement from >=61.0 to >=82.0.1 #5

chore(deps-dev): update setuptools requirement from >=61.0 to >=82.0.1

chore(deps-dev): update setuptools requirement from >=61.0 to >=82.0.1 #5

name: Branch Lifecycle Automation
on:
issues:
types: [labeled]
pull_request:
types: [opened, synchronize, closed]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
auto-create-branch:
name: Auto-Create Branch from Issue
if: github.event_name == 'issues' && github.event.label.name == 'ready'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create branch from issue
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const issueNumber = issue.number;
const issueTitle = issue.title;
// Determine branch prefix from labels
let branchPrefix = 'feature';
const labels = issue.labels.map(l => l.name);
if (labels.includes('bug')) {
branchPrefix = 'fix';
} else if (labels.includes('documentation')) {
branchPrefix = 'docs';
} else if (labels.includes('enhancement') || labels.includes('feature')) {
branchPrefix = 'feature';
}
// Create slug from issue title
const slug = issueTitle
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '')
.substring(0, 30);
const branchName = `${branchPrefix}-${issueNumber}-${slug}`;
// Check if branch already exists
try {
await github.rest.repos.getBranch({
owner: context.repo.owner,
repo: context.repo.repo,
branch: branchName,
});
console.log(`Branch ${branchName} already exists, skipping creation`);
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `ℹ️ Branch \`${branchName}\` already exists. You can start working on it:\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${branchName}\n\`\`\``,
});
return;
} catch (error) {
if (error.status !== 404) throw error;
}
// Get dev branch SHA
const { data: devBranch } = await github.rest.repos.getBranch({
owner: context.repo.owner,
repo: context.repo.repo,
branch: 'dev',
});
// Create new branch from dev
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/heads/${branchName}`,
sha: devBranch.commit.sha,
});
console.log(`Created branch: ${branchName}`);
// Add comment to issue
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `✅ Branch created: \`${branchName}\`\n\nYou can start working on this issue:\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${branchName}\n\`\`\`\n\nWhen ready, push your changes and a PR will be automatically created.`,
});
// Add "in-progress" label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: ['in-progress'],
});
auto-update-branch:
name: Auto-Update Branch Before Merge
if: github.event_name == 'pull_request' && github.event.action == 'synchronize' && github.event.pull_request.base.ref == 'dev'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.ref }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Rebase on dev
id: rebase
continue-on-error: true
run: |
git fetch origin dev
# Check if rebase is needed
if git merge-base --is-ancestor origin/dev HEAD; then
echo "Branch is up-to-date with dev"
echo "rebase_needed=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "Rebasing on dev..."
if git rebase origin/dev; then
echo "rebase_needed=true" >> $GITHUB_OUTPUT
echo "rebase_success=true" >> $GITHUB_OUTPUT
git push --force-with-lease
else
echo "rebase_needed=true" >> $GITHUB_OUTPUT
echo "rebase_success=false" >> $GITHUB_OUTPUT
git rebase --abort
fi
- name: Comment on conflict
if: steps.rebase.outputs.rebase_success == 'false'
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `⚠️ **Merge Conflict Detected**\n\nThis branch has conflicts with \`dev\`. Please resolve them manually:\n\n\`\`\`bash\ngit fetch origin\ngit rebase origin/dev\n# Resolve conflicts\ngit rebase --continue\ngit push --force-with-lease\n\`\`\``,
});
auto-delete-branch:
name: Auto-Delete Merged Branch
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Delete merged branch
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const branchName = pr.head.ref;
// Don't delete protected branches
if (['main', 'dev', 'develop', 'master'].includes(branchName)) {
console.log(`Skipping deletion of protected branch: ${branchName}`);
return;
}
try {
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${branchName}`,
});
console.log(`Deleted branch: ${branchName}`);
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: `✅ Branch \`${branchName}\` has been automatically deleted after merge.`,
});
} catch (error) {
console.log(`Could not delete branch ${branchName}: ${error.message}`);
}
auto-close-issue:
name: Auto-Close Linked Issue
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Close linked issue
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const branchName = pr.head.ref;
// Extract issue number from branch name (format: {type}-{number}-{slug})
const match = branchName.match(/^(?:feature|fix|docs|refactor)-(\d+)-/);
if (!match) {
console.log(`No issue number found in branch name: ${branchName}`);
return;
}
const issueNumber = parseInt(match[1], 10);
try {
// Check if issue exists and is open
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
if (issue.state === 'open') {
// Close the issue
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
state: 'closed',
});
// Add comment linking to PR
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: `✅ Closed automatically by merging PR #${pr.number}`,
});
// Remove "in-progress" label and add "completed"
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
name: 'in-progress',
});
} catch (e) {
// Label might not exist
}
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: ['completed'],
});
console.log(`Closed issue #${issueNumber}`);
}
} catch (error) {
console.log(`Could not close issue #${issueNumber}: ${error.message}`);
}