Skip to content

Commit 5a2acad

Browse files
authored
Replace dotnet/actions-create-pull-request with local composite action (#15964)
* Fix broken actions after a break due to incompatibility between checkout step and create-pull-request action. * Address PR review feedback: token auth, labels desc, operation output, body writing, docs prefix
1 parent a4dad19 commit 5a2acad

File tree

10 files changed

+146
-10
lines changed

10 files changed

+146
-10
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
name: 'Create Pull Request'
2+
description: 'Creates or updates a pull request for changes to the repository'
3+
inputs:
4+
token:
5+
description: 'GitHub token for authentication'
6+
required: true
7+
branch:
8+
description: 'The pull request branch name'
9+
required: true
10+
base:
11+
description: 'The base branch for the pull request'
12+
required: false
13+
default: 'main'
14+
title:
15+
description: 'The title of the pull request'
16+
required: true
17+
body:
18+
description: 'The body of the pull request'
19+
required: true
20+
labels:
21+
description: 'A newline-separated list of labels'
22+
required: false
23+
default: ''
24+
commit-message:
25+
description: 'The commit message to use when committing changes'
26+
required: false
27+
default: '[create-pull-request] automated change'
28+
branch-already-exists:
29+
description: 'Set to true if the branch is already pushed remotely (skips commit/push)'
30+
required: false
31+
default: 'false'
32+
outputs:
33+
pull-request-number:
34+
description: 'The pull request number'
35+
value: ${{ steps.create-pr.outputs.pull-request-number }}
36+
pull-request-url:
37+
description: 'The URL of the pull request'
38+
value: ${{ steps.create-pr.outputs.pull-request-url }}
39+
pull-request-operation:
40+
description: 'The pull request operation performed (created, updated, none)'
41+
value: ${{ steps.create-pr.outputs.pull-request-operation }}
42+
runs:
43+
using: 'composite'
44+
steps:
45+
- name: Configure git authentication
46+
shell: bash
47+
env:
48+
GH_TOKEN: ${{ inputs.token }}
49+
run: |
50+
# Use the provided token for both git and gh operations
51+
gh auth setup-git
52+
53+
- name: Commit and push changes
54+
if: inputs.branch-already-exists != 'true'
55+
id: commit-and-push
56+
shell: bash
57+
env:
58+
BRANCH: ${{ inputs.branch }}
59+
COMMIT_MESSAGE: ${{ inputs.commit-message }}
60+
run: |
61+
# Check for any changes (staged, unstaged, or untracked)
62+
if git diff --quiet && git diff --cached --quiet && [ -z "$(git ls-files --others --exclude-standard)" ]; then
63+
echo "No changes to commit"
64+
echo "has_changes=false" >> $GITHUB_OUTPUT
65+
exit 0
66+
fi
67+
68+
echo "has_changes=true" >> $GITHUB_OUTPUT
69+
70+
git config user.name "github-actions[bot]"
71+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
72+
73+
# Create or reset branch
74+
git checkout -B "$BRANCH"
75+
git add -A
76+
git commit -m "$COMMIT_MESSAGE"
77+
git push -f origin "$BRANCH"
78+
79+
- name: Create or update pull request
80+
id: create-pr
81+
if: inputs.branch-already-exists == 'true' || steps.commit-and-push.outputs.has_changes == 'true'
82+
shell: bash
83+
env:
84+
GH_TOKEN: ${{ inputs.token }}
85+
BRANCH: ${{ inputs.branch }}
86+
BASE: ${{ inputs.base }}
87+
PR_TITLE: ${{ inputs.title }}
88+
PR_BODY: ${{ inputs.body }}
89+
LABELS: ${{ inputs.labels }}
90+
run: |
91+
# Check if a PR already exists for this branch
92+
EXISTING_PR=$(gh pr list --head "$BRANCH" --base "$BASE" --json number,url --jq '.[0] // empty')
93+
94+
if [ -n "$EXISTING_PR" ]; then
95+
PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.number')
96+
PR_URL=$(echo "$EXISTING_PR" | jq -r '.url')
97+
echo "Pull request #$PR_NUMBER already exists: $PR_URL"
98+
echo "pull-request-number=$PR_NUMBER" >> $GITHUB_OUTPUT
99+
echo "pull-request-url=$PR_URL" >> $GITHUB_OUTPUT
100+
echo "pull-request-operation=none" >> $GITHUB_OUTPUT
101+
else
102+
# Build label arguments as a bash array (avoids eval/injection)
103+
LABEL_ARGS=()
104+
if [ -n "$LABELS" ]; then
105+
while IFS= read -r label; do
106+
label=$(echo "$label" | xargs) # trim whitespace
107+
if [ -n "$label" ]; then
108+
LABEL_ARGS+=(--label "$label")
109+
fi
110+
done <<< "$LABELS"
111+
fi
112+
113+
# Write body to a temp file to avoid shell quoting issues with special characters
114+
BODY_FILE=$(mktemp)
115+
trap 'rm -f "$BODY_FILE"' EXIT
116+
printf '%s\n' "$PR_BODY" > "$BODY_FILE"
117+
118+
# Create the pull request without eval — all args are properly quoted
119+
PR_URL=$(gh pr create \
120+
--title "$PR_TITLE" \
121+
--body-file "$BODY_FILE" \
122+
--base "$BASE" \
123+
--head "$BRANCH" \
124+
"${LABEL_ARGS[@]}")
125+
126+
rm -f "$BODY_FILE"
127+
trap - EXIT
128+
129+
PR_NUMBER=$(gh pr view "$BRANCH" --json number --jq '.number')
130+
echo "Created pull request #$PR_NUMBER: $PR_URL"
131+
echo "pull-request-number=$PR_NUMBER" >> $GITHUB_OUTPUT
132+
echo "pull-request-url=$PR_URL" >> $GITHUB_OUTPUT
133+
echo "pull-request-operation=created" >> $GITHUB_OUTPUT
134+
fi

.github/workflows/generate-api-diffs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
3535

3636
- name: Create or update pull request
37-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
37+
uses: ./.github/actions/create-pull-request
3838
with:
3939
token: ${{ steps.app-token.outputs.token }}
4040
branch: update-api-diffs

.github/workflows/generate-ats-diffs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
8585

8686
- name: Create or update pull request
87-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
87+
uses: ./.github/actions/create-pull-request
8888
with:
8989
token: ${{ steps.app-token.outputs.token }}
9090
branch: update-ats-diffs

.github/workflows/refresh-manifests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
3535

3636
- name: Create or update pull request
37-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
37+
uses: ./.github/actions/create-pull-request
3838
with:
3939
token: ${{ steps.app-token.outputs.token }}
4040
branch: update-manifests

.github/workflows/refresh-typescript-sdks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
./eng/refreshTypeScriptSdks.ps1
3333
3434
- name: Create or update pull request
35-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
35+
uses: ./.github/actions/create-pull-request
3636
with:
3737
token: ${{ secrets.GITHUB_TOKEN }}
3838
branch: update-typescript-playground-sdks

.github/workflows/release-github-tasks.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ jobs:
356356
357357
- name: Create Merge PR
358358
if: steps.check-pr.outputs.pr_exists != 'true' && inputs.dry_run != true
359-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1 # v1
359+
uses: ./.github/actions/create-pull-request
360360
with:
361361
token: ${{ steps.app-token.outputs.token }}
362362
title: "Merge ${{ inputs.release_branch }} to main after v${{ inputs.release_version }} release"
@@ -372,6 +372,7 @@ jobs:
372372
*Created automatically by the release workflow.*
373373
branch: ${{ inputs.release_branch }}
374374
base: main
375+
branch-already-exists: 'true'
375376
labels: |
376377
area-infrastructure
377378
release-automation
@@ -476,7 +477,7 @@ jobs:
476477
477478
- name: Create Baseline PR
478479
if: steps.check-pr.outputs.pr_exists != 'true' && inputs.dry_run != true
479-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1 # v1
480+
uses: ./.github/actions/create-pull-request
480481
with:
481482
token: ${{ steps.app-token.outputs.token }}
482483
title: "Update PackageValidationBaselineVersion to ${{ inputs.release_version }}"
@@ -492,6 +493,7 @@ jobs:
492493
*Created automatically by the release workflow.*
493494
branch: update-baseline-${{ inputs.release_version }}
494495
base: main
496+
branch-already-exists: 'true'
495497
labels: |
496498
area-infrastructure
497499
release-automation

.github/workflows/update-ai-foundry-models.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
3232

3333
- name: Create or update pull request
34-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
34+
uses: ./.github/actions/create-pull-request
3535
with:
3636
token: ${{ steps.app-token.outputs.token }}
3737
branch: update-ai-foundry-models

.github/workflows/update-dependencies.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848

4949
- name: Create Pull Request
5050
id: create-pr
51-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
51+
uses: ./.github/actions/create-pull-request
5252
with:
5353
token: ${{ steps.app-token.outputs.token }}
5454
branch: update-dependencies

.github/workflows/update-github-models.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
private-key: ${{ secrets.ASPIRE_BOT_PRIVATE_KEY }}
3333

3434
- name: Create or update pull request
35-
uses: dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1
35+
uses: ./.github/actions/create-pull-request
3636
with:
3737
token: ${{ steps.app-token.outputs.token }}
3838
branch: update-github-models

docs/release-process.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ The pipeline uses the `Aspire-Release-Secrets` variable group. Note that NuGet p
150150
The workflow uses only pre-approved actions:
151151

152152
- `actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683` (v4)
153-
- `dotnet/actions-create-pull-request@e8d799aa1f8b17f324f9513832811b0a62f1e0b1` (v1)
153+
- `./.github/actions/create-pull-request` (local composite action)
154154

155155
## Troubleshooting
156156

0 commit comments

Comments
 (0)