Skip to content

Pull Request Mutation: main #1

Pull Request Mutation: main

Pull Request Mutation: main #1

Workflow file for this run

name: "Pull Request Mutation"
run-name: "Pull Request Mutation: ${{ github.event.workflow_run.head_branch }}"
on:
workflow_run:
workflows:
- Build
types:
- completed
concurrency:
group: "mutation-${{ github.event.workflow_run.head_branch }}"
cancel-in-progress: true
permissions:
contents: read
packages: read
statuses: write
jobs:
mutate:
runs-on: ubuntu-latest
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'failure' && (!contains(fromJSON('["main", "dev"]'), github.event.workflow_run.head_branch) || github.event.workflow_run.head_repository.fork)
steps:
- name: Download artifacts
id: download-artifacts
uses: dawidd6/action-download-artifact@v2
with:
github_token: ${{secrets.GITHUB_TOKEN}}
run_id: ${{ github.event.workflow_run.id }}
name: .+\.diff$
name_is_regexp: true
if_no_artifact_found: ignore
path: patches
- uses: marocchino/action-workflow_run-status@54b6e87d6cb552fc5f36dbe9a722a6048725917a
if: steps.download-artifacts.outputs.found_artifact == 'true'
with:
github_token: ${{secrets.GITHUB_TOKEN}}
- name: Token check
if: steps.download-artifacts.outputs.found_artifact == 'true'
run: |
if ${{ secrets.MUTATION_TOKEN && 'true' || 'false' }}; then
echo "Token available, enabling self mutation"
exit 0
else
echo "Add a MUTATION_TOKEN repository secret with a personal access token to enable self mutation.
It requires private repo read/write permissions." >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Disable Git Hooks
if: steps.download-artifacts.outputs.found_artifact == 'true'
run: |
git config --global core.hooksPath /dev/null
- name: Update PR Branch
uses: actions/github-script@v6
if: github.event.workflow_run.event == 'pull_request' && steps.download-artifacts.outputs.found_artifact == 'true'
with:
github-token: ${{ secrets.MUTATION_TOKEN }}
script: |
// use API to get the PR data since we can't rely on the context across forks
const pulls = await github.rest.pulls.list({
per_page: 1,
owner: context.repo.owner,
repo: context.repo.repo,
head: `${context.payload.workflow_run.head_repository.full_name}:${context.payload.workflow_run.head_branch}`
});
const prContextData = pulls.data[0];
const prNumber = prContextData.number;
const originalSha = prContextData.head.sha;
try {
console.log("Updating PR branch");
await github.rest.pulls.updateBranch({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
console.log("PR branch updated");
let updatedSha = originalSha;
let retries = 0;
const MAX_RETRIES = 10;
while (updatedSha == originalSha && retries++ < MAX_RETRIES) {
console.log(`Waiting for PR branch to update (attempt ${retries}/${MAX_RETRIES})`);
await new Promise(r => setTimeout(r, 500));
const updatedPR = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
updatedSha = updatedPR.data.head.sha;
}
} catch (error) {
// The branch is already up to date or can't otherwise be updated
// That's fine, we tried our best
console.warn(error);
}
- name: Checkout Workflow Branch
if: steps.download-artifacts.outputs.found_artifact == 'true'
uses: actions/checkout@v3
with:
token: ${{ secrets.MUTATION_TOKEN }}
ref: ${{ github.event.workflow_run.head_branch }}
repository: ${{ github.event.workflow_run.head_repository.full_name }}
path: repo
- id: self_mutation
if: steps.download-artifacts.outputs.found_artifact == 'true'
name: Apply downloaded patches
working-directory: repo
env:
HEAD_REF: ${{ github.event.workflow_run.head_branch }}
run: |
git config user.name "monada-bot[bot]"
git config user.email "[email protected]"
for f in $(find ../patches/*.diff/*.diff); do
echo "Applying $f"
git apply --binary $f
if [ $? -eq 0 ]; then
git add --all
git commit -s -m "chore: self mutation ($(basename $f))"
echo "Patch applied successfully"
rm $f
else
echo "Patch failed to apply"
cat $f
exit 1
fi
done
git push origin HEAD:$HEAD_REF
- name: Add label to block auto merge
uses: actions/github-script@v6
if: github.event.workflow_run.event == 'pull_request' && steps.download-artifacts.outputs.found_artifact == 'true'
with:
github-token: ${{ secrets.MUTATION_TOKEN }}
script: |
// use API to get the PR number since we can't rely on the context across forks
const pulls = await github.rest.pulls.list({
per_page: 1,
owner: context.repo.owner,
repo: context.repo.repo,
head: `${context.payload.workflow_run.head_repository.full_name}:${context.payload.workflow_run.head_branch}`
});
const prNumber = pulls.data[0].number;
const labels = ["⚠️ pr/review-mutation"];
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
labels: labels
});