Files
recipes/.github/workflows/create-upstream-pr.yml
GitHub Action bf574c16f4 Restore upstream infrastructure files for PR
- Removed fork-specific .gitattributes
- Restored upstream .github/workflows/
- Restored upstream cookbook/version_info.py
2025-12-08 04:39:11 +00:00

236 lines
10 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Create Upstream PR
on:
workflow_run:
workflows: ["Push Workflow"]
types:
- completed
branches: [working]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
create-upstream-pr:
runs-on: ubuntu-latest
concurrency:
group: upstream-pr
cancel-in-progress: true
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
steps:
- name: Generate GitHub App token (for branch push)
id: generate_token_push
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.BOT_APP_ID }}
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
- name: Checkout fork
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.generate_token_push.outputs.token }}
- name: Setup git user
run: |
git config user.name "GitHub Action"
git config user.email "action@github.com"
- name: Add upstream remote
run: |
git remote get-url upstream || git remote add upstream https://github.com/TandoorRecipes/recipes.git
git fetch upstream
- name: Ensure jq is available
run: |
if ! command -v jq &> /dev/null; then
sudo apt-get update && sudo apt-get install -y jq
fi
- name: Create upstream PR branch
id: create_branch
run: |
BRANCH_NAME="upstream-pr-$(date +%Y%m%d-%H%M%S)"
git checkout -b "$BRANCH_NAME" || { echo "❌ Failed to create branch $BRANCH_NAME"; exit 1; }
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
echo "✅ Created branch: $BRANCH_NAME"
- name: Restore upstream infrastructure files
id: restore_infra
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
git checkout "$BRANCH_NAME"
git rm .gitattributes || echo " .gitattributes not present, skipping removal."
git checkout upstream/tandoor-1 -- .github/workflows/ || echo " No workflows to restore."
git checkout upstream/tandoor-1 -- cookbook/version_info.py || echo " No version_info.py to restore."
git add .
if ! git diff --cached --quiet; then
git commit -m $'Restore upstream infrastructure files for PR\n\n- Removed fork-specific .gitattributes\n- Restored upstream .github/workflows/\n- Restored upstream cookbook/version_info.py'
echo "✅ Infrastructure files restored and committed."
else
echo " No infrastructure changes to commit."
fi
- name: Push branch to fork (after infra commit)
env:
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
echo "Pushing branch $BRANCH_NAME after infra file restore."
git push --set-upstream https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
echo "✅ Branch pushed: $BRANCH_NAME (infra files)"
- name: Merge upstream branch
id: merge_upstream
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
git checkout "$BRANCH_NAME"
if git merge --no-edit upstream/tandoor-1; then
echo "✅ Merged upstream/tandoor-1 into $BRANCH_NAME"
if ! git diff --cached --quiet || [ -n "$(git log origin/$BRANCH_NAME..$BRANCH_NAME --oneline)" ]; then
echo "merge_commit=true" >> $GITHUB_OUTPUT
else
echo "merge_commit=false" >> $GITHUB_OUTPUT
fi
else
echo "❌ Merge conflict detected during merge with upstream/tandoor-1. Please resolve conflicts manually." >&2
exit 1
fi
- name: Push branch to fork (after merge)
if: steps.merge_upstream.outputs.merge_commit == 'true'
env:
GITHUB_TOKEN: ${{ steps.generate_token_push.outputs.token }}
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
echo "Pushing branch $BRANCH_NAME after merge."
git push https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git "$BRANCH_NAME"
echo "✅ Branch pushed: $BRANCH_NAME (after merge)"
- name: Get commit list
id: get_commits
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
COMMITS_RAW=$(git log upstream/tandoor-1..$BRANCH_NAME --oneline)
if [ -z "$COMMITS_RAW" ]; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "✅ No commits to contribute - exiting gracefully"
exit 0
fi
echo "commits_raw<<EOF" >> $GITHUB_OUTPUT
printf "%s\n" "$COMMITS_RAW" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "has_changes=true" >> $GITHUB_OUTPUT
- name: Get changed files
id: get_files
run: |
BRANCH_NAME="${{ steps.create_branch.outputs.branch_name }}"
CHANGED_FILES=$(git diff upstream/tandoor-1..$BRANCH_NAME --name-only)
echo "changed_files<<EOF" >> $GITHUB_OUTPUT
printf "%s\n" "$CHANGED_FILES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
CODE_COUNT=$(echo "$CHANGED_FILES" | grep -c '^' || true)
echo "code_count=$CODE_COUNT" >> $GITHUB_OUTPUT
- name: Summarize changes
id: summarize_changes
run: |
CODE_COUNT=${{ steps.get_files.outputs.code_count }}
CHANGES_SUMMARY="Modified $CODE_COUNT code files"
echo "changes_summary=$CHANGES_SUMMARY" >> $GITHUB_OUTPUT
- name: Prepare commit subjects and JSON
id: prepare_commits
run: |
COMMITS_RAW="${{ steps.get_commits.outputs.commits_raw }}"
CODE_FILES=( $(echo "${{ steps.get_files.outputs.changed_files }}") )
FILTERED_COMMITS_JSON="[]"
COMMIT_SUBJECTS_ARRAY=()
INFRA_PATTERNS='^\.github/|^cookbook/version_info\.py$|^\.gitattributes$'
while IFS= read -r commit_line; do
if [ -z "$commit_line" ]; then continue; fi
COMMIT_SHA=$(echo "$commit_line" | cut -d' ' -f1)
COMMIT_SUBJECT=$(echo "$commit_line" | cut -d' ' -f2-)
mapfile -t COMMIT_FILES < <(git diff-tree --no-commit-id --name-only -r "$COMMIT_SHA" | grep -Ev "$INFRA_PATTERNS")
# Only include commit if it touches at least one non-infra file that is still different
INCLUDE_COMMIT=false
for file in "${COMMIT_FILES[@]}"; do
for code_file in "${CODE_FILES[@]}"; do
if [ "$file" = "$code_file" ]; then
INCLUDE_COMMIT=true
break 2
fi
done
done
if [ "$INCLUDE_COMMIT" = true ]; then
COMMIT_SUBJECTS_ARRAY+=("- $COMMIT_SUBJECT")
FILES_JSON=$(printf '%s\n' "${COMMIT_FILES[@]}" | jq -R . | jq -s .)
COMMIT_JSON=$(jq -n --arg sha "$COMMIT_SHA" --arg subject "$COMMIT_SUBJECT" --argjson files "$FILES_JSON" '{sha: $sha, subject: $subject, files: $files}')
FILTERED_COMMITS_JSON=$(echo "$FILTERED_COMMITS_JSON" | jq --argjson item "$COMMIT_JSON" '. + [$item]')
fi
done <<< "$COMMITS_RAW"
echo 'commits_json<<EOF' >> $GITHUB_OUTPUT
printf "%s\n" "$FILTERED_COMMITS_JSON" >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
echo "commit_subjects<<EOF" >> $GITHUB_OUTPUT
printf '%s\n' "${COMMIT_SUBJECTS_ARRAY[@]}" >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
- name: Build PR content
if: steps.get_commits.outputs.has_changes == 'true'
id: build_pr_content
uses: actions/github-script@v7
env:
COMMITS_JSON: ${{ steps.prepare_commits.outputs.commits_json }}
CHANGES_SUMMARY: ${{ steps.summarize_changes.outputs.changes_summary }}
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
with:
github-token: ${{ steps.generate_token_push.outputs.token }}
script: |
const commits = JSON.parse(process.env.COMMITS_JSON || '[]');
const changesSummary = process.env.CHANGES_SUMMARY || 'Changes from fork';
const branchName = process.env.BRANCH_NAME || '';
const repo = process.env.GITHUB_REPOSITORY || '';
const [owner, reponame] = repo.split('/');
const nCommits = commits.length;
let prTitle = 'Sync ' + nCommits + ' commit' + (nCommits !== 1 ? 's' : '') + ' from fork:';
if (nCommits > 0) {
prTitle += ' ' + commits[0].subject;
}
let prBody = `This PR syncs ${nCommits} commit${nCommits !== 1 ? 's' : ''} from branch ${branchName}.\n\n`;
prBody += `**Changes Summary:**\n${changesSummary}\n\n`;
prBody += `Commits included:\n`;
for (const c of commits) {
prBody += `- ${c.subject} ([${c.sha}](https://github.com/${owner}/${reponame}/commit/${c.sha}))\n`;
}
prBody += `\n---\n`;
core.setOutput('prTitle', prTitle);
core.setOutput('prBody', prBody);
- name: Print PR creation instructions
if: steps.get_commits.outputs.has_changes == 'true'
env:
BRANCH_NAME: ${{ steps.create_branch.outputs.branch_name }}
PR_TITLE: ${{ steps.build_pr_content.outputs.prTitle }}
PR_BODY: ${{ steps.build_pr_content.outputs.prBody }}
run: |
echo "✅ Branch pushed: $BRANCH_NAME"
echo
echo "To create a pull request, open:"
echo "https://github.com/TandoorRecipes/recipes/compare/tandoor-1...${{ github.repository_owner }}:$BRANCH_NAME?expand=1"
echo
echo "Suggested PR title:"
echo "$PR_TITLE"
echo
echo "Suggested PR body:"
echo "$PR_BODY"