create-pull-request
create-pull-request copied to clipboard
Private GH repo: Cannot read properties of undefined (reading 'number')
Hello, I'm facing the same issue as #2790 with v7.0.6.
This is a private repo, and I'm pinning to v7.0.6 explicitly. The PR was created successfully, but it isn't getting updated. More specifically, the PR is being force-pushed but the title and body isn't being updated.
Running on ubuntu-24.04. I've tried using v6.0.1 to no avail.
Logs:
Run peter-evans/[email protected]
with:
token: ***
sign-commits: true
commit-message: chore(release): release TOOL 0.10.0
title: chore(release): release TOOL 0.10.0
body: ## TOOL [0.10.0](https://github.com/org/repo/tree/0.10.0)
branch: release
committer: user[bot] <blah.user[bot]@users.noreply.github.com>
author: user[bot] <blah.user[bot]@users.noreply.github.com>
delete-branch: true
labels: auto
signoff: false
draft: false
maintainer-can-modify: true
Fetching existing pull request
Attempting update of pull request
Error: Cannot read properties of undefined (reading 'number')
Code:
- name: Update PR
uses: peter-evans/[email protected]
with:
token: ${{ steps.get-app-token.outputs.token }}
sign-commits: true
commit-message: ${{ needs.determine-title.outputs.title }}
title: ${{ needs.determine-title.outputs.title }}
body: ${{ steps.get-changelog-entry.outputs.draft-output }}
branch: release
committer: '${{ env.GIT_AUTHOR_USERNAME }} <${{ env.GIT_AUTHOR_EMAIL }}>'
author: '${{ env.GIT_AUTHOR_USERNAME }} <${{ env.GIT_AUTHOR_EMAIL }}>'
delete-branch: true
labels: auto
Hi @ayussh-verma
Is release an existing branch? If so, that's not how this action works. The branch input is the PR branch that the action creates and manages itself.
If you show me your full workflow I might be able to help you better. It matters how the workflow is triggered, and how you are making changes before the action runs.
Hey @peter-evans, no the release branch is created by this action itself.
Basically, this is a release pipeline. I run the workflow with a version input which bumps my projects version and creates a PR for it (and pushes Docker images, etc). The PR title is dependent on the workflow input. If the release can't go through, I run the workflow again with a new semver. The action then force pushes the branch correctly, but then encounters this error when it tries to update the PR title.
If I approve the changes the workflow merges the PR. so the PR is short-lived.
This is the simplified workflow:
on:
# Prepare the release
workflow_dispatch:
inputs:
version:
description: "Release version (Following semver, e.g., 1.2.3)"
required: true
# Finalize the release
pull_request_review:
types: [submitted]
concurrency:
group: ${{ github.workflow }}
jobs:
prepare-release:
if: ${{ workflow_dispatch ]]
steps:
- name: Bump version
run: modify semver
- name: Get changelog
run: build changelog
- name: Determine PR title
id: determine-title
run: build title from semver workflow_dispatch
- name: Update PR
id: update-pr
uses: peter-evans/[email protected]
with:
commit-message: ${{ determine-title }}
title: ${{ determine-title }}
body: ${{ get-changelog }}
branch: release
delete-branch: true
continue-on-error: true
# This step is what the action is failing to do.
- name: Update the PR body and title
id: update-pr-temp
run: |
pr_number=$(fetch release PR)
gh pr edit "${pr_number}" --body {{ get-changelog }} --title {{ determine-title }}
ref=$(gh pr view --json headRefOid --jq '.headRefOid')
echo "pull-request-head-sha=${ref}" >> "${GITHUB_OUTPUT}"
finalize-release:
if: ${{
github.event_name == 'pull_request_review'
&& github.event.review.state == 'approved'
}}
steps:
- name: Get the semver from the PR title
id: get-semver
run: title | awk ${NF}
- name: Tag the git commit
run: git tag head_ref
- name: Create a GitHub release from the git tag
- name: Merge the PR
run: gh pr merge --merge --delete-branch
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
And if you want to see the exact workflow:
name: Release
on:
# Prepare the release
workflow_dispatch:
inputs:
version:
description: "Release version (Following semver, e.g., 1.2.3)"
required: true
# Finish the release
pull_request_review:
types: [submitted]
concurrency:
group: ${{ github.workflow }}
env:
GIT_AUTHOR_USERNAME: 'bot-bot[bot]'
GIT_AUTHOR_EMAIL: '1203103120+bot-bot[bot]@users.noreply.github.com'
MESSAGE_PREFIX: 'chore(release): release TOOL'
DOCKER_IMAGE_PATH: 'ghcr.io/${{ github.repository }}'
PRE_RELEASE_IMAGE_PREFIX: 'pre-release'
jobs:
clean-dispatch-inputs:
if: ${{ github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-24.04
timeout-minutes: ${{ fromJSON(vars.SHORT_TIMEOUT) }}
outputs:
semver: ${{ steps.clean-version.outputs.version }}
steps:
- name: Fail if the workflow hasn't been triggered from main
if: ${{ github.ref != 'refs/heads/main' }}
run: echo 'Releases must be made from the main branch' && exit 1
- name: Fail if the version is not a valid semver
run: |
version='${{ github.event.inputs.version }}'
if ! [[ "${version}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version: ${version}. Must follow semver (e.g., 1.2.3)."
exit 1
fi
- name: Clean up the version
id: clean-version
run: |
version='${{ github.event.inputs.version }}'
if [[ "${version}" == v* ]]; then
version="${version:1}"
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"
prepare-release:
runs-on: ubuntu-24.04
timeout-minutes: ${{ fromJSON(vars.MODERATE_TIMEOUT) }}
needs: clean-dispatch-inputs
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup project tooling
uses: ./.github/actions/setup-tools
with:
install-pre-commit: false
- name: Bump pyproject.toml version
shell: uv run --script {0}
run: |
import tomlkit
with open("pyproject.toml") as f:
pyproject_data = tomlkit.load(f)
new_version = "${{ needs.clean-dispatch-inputs.outputs.semver }}"
pyproject_data["project"]["version"] = new_version
with open("pyproject.toml", "w") as f:
tomlkit.dump(pyproject_data, f)
- name: Install new project version
run: uv sync
- name: Get towncrier CHANGELOG entry contents
id: get-changelog-entry
# PR Title will be chore(release): release SCALE DB Utility vx.y.z
# PR Body will be the lines added to CHANGELOG.md
run: |
draft=$(uv run towncrier build --draft)
echo "draft-output<<EOF" >> "${GITHUB_OUTPUT}"
echo "${draft}" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"
- name: Get app token
id: get-app-token
uses: actions/create-github-app-token@v1
with:
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
app-id: ${{ secrets.GH_APP_ID }}
owner: ${{ github.repository_owner }}
- name: Determine PR title after adding the semver
id: determine-title
run: |
title="${MESSAGE_PREFIX} ${{ needs.clean-dispatch-inputs.outputs.semver }}"
echo "title=${title}" >> "${GITHUB_OUTPUT}"
- name: Update PR
id: update-pr
uses: peter-evans/[email protected]
with:
token: ${{ steps.get-app-token.outputs.token }}
sign-commits: true
commit-message: ${{ steps.determine-title.outputs.title }}
title: ${{ steps.determine-title.outputs.title }}
body: ${{ steps.get-changelog-entry.outputs.draft-output }}
branch: release
committer: '${{ env.GIT_AUTHOR_USERNAME }} <${{ env.GIT_AUTHOR_EMAIL }}>'
author: '${{ env.GIT_AUTHOR_USERNAME }} <${{ env.GIT_AUTHOR_EMAIL }}>'
delete-branch: true
labels: auto
continue-on-error: true # FIXME: Remove this when the upstream issue gets fixed
# FIXME: Remove this when the upstream issue gets fixed
- name: Update the PR body and title
id: update-pr-temp
run: |
# Wait a bit for the REST API to catch up
sleep 10
pr_number=$(gh pr list --state open --base main --json number,title | jq -r '.[] | select(.title | startswith("chore(release): release SCALE DB Utility")) | .number')
gh pr edit "${pr_number}" --body "${{ steps.get-changelog-entry.outputs.draft-output }}" --title "${{ steps.determine-title.outputs.title }}"
ref=$(gh pr view "${pr_number}" --json headRefOid --jq '.headRefOid')
echo "pull-request-head-sha=${ref}" >> "${GITHUB_OUTPUT}"
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get SHAs
id: get-shas
run: |
tag='${{ steps.update-pr-temp.outputs.pull-request-head-sha }}'
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
short_tag=$(cut -c 1-7 <<< "${tag}")
echo "short-tag=${short_tag}" >> "${GITHUB_OUTPUT}"
- name: Generate image tags
id: pre-release-tags
shell: python {0}
run: |
import os
semver = "${{ needs.clean-dispatch-inputs.outputs.semver }}"
PRE_RELEASE_PREFIX = os.environ['PRE_RELEASE_IMAGE_PREFIX']
image_path = "${{ env.DOCKER_IMAGE_PATH }}".lower()
cache_tag = f"{image_path}:cache"
pre_release_tag = f"{image_path}:{PRE_RELEASE_PREFIX}"
tag_with_semver = f"{image_path}:{PRE_RELEASE_PREFIX}-{semver}"
full_sha = "${{ steps.get-shas.outputs.tag }}"
short_sha = "${{ steps.get-shas.outputs.short-tag }}"
absolute_tag = f"{tag_with_semver}-{full_sha}"
tags = [
cache_tag,
pre_release_tag,
absolute_tag,
f"{tag_with_semver}-{short_sha}"
]
with open(os.environ['GITHUB_OUTPUT'], "a") as f:
print(f"cache-tag={cache_tag}", file=f)
print(f"absolute-tag={absolute_tag}", file=f)
print("tags<<EOF", file=f)
for tag in tags:
print(tag, file=f)
print("EOF", file=f)
- name: Checkout PR
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: release
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
provenance: mode=max
sbom: true
push: true
cache-from: type=registry,ref=${{ steps.pre-release-tags.outputs.cache-tag }}
cache-to: type=inline
tags: ${{ steps.pre-release-tags.outputs.tags }}
- name: Smoke test the Docker image
run: |
docker run --rm ${{ steps.pre-release-tags.outputs.absolute-tag }} --help
docker run --rm ${{ steps.pre-release-tags.outputs.absolute-tag }} --version
finalize-release:
if: ${{
github.event_name == 'pull_request_review'
&& github.event.review.state == 'approved'
&& github.event.pull_request.head.ref == 'release'
&& github.repository == github.event.pull_request.head.repo.full_name
}}
runs-on: ubuntu-24.04
timeout-minutes: ${{ fromJSON(vars.MODERATE_TIMEOUT) }}
# Tag the git commit with the semver, push the docker image, create a GitHub release from that tag
# if everything is successful, merge the pr and delete the feature branch
steps:
- name: Checkout PR
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: release
- name: Get app token
id: get-app-token
uses: actions/create-github-app-token@v1
with:
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
app-id: ${{ secrets.GH_APP_ID }}
owner: ${{ github.repository_owner }}
- name: Parse PR semver
id: get-semver
run: |
title='${{ github.event.pull_request.title }}'
# semver is just 'MESSAGE_PREFIX x.y.z'
semver=$(echo "${title}" | awk '{print $NF}')
echo "semver=${semver}" >> "${GITHUB_OUTPUT}"
- name: Tag the git commit
run: >
gh api 'repos/${{ github.repository }}/git/refs'
-f ref='refs/tags/${{ steps.get-semver.outputs.semver }}'
-f sha='${{ github.event.pull_request.head.sha }}'
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get new image tags
id: get-new-tags
shell: python {0}
run: |
import os
PRE_RELEASE_PREFIX = os.environ['PRE_RELEASE_IMAGE_PREFIX']
image_path = "${{ env.DOCKER_IMAGE_PATH }}".lower()
semver = "${{ steps.get-semver.outputs.semver }}"
head_sha = "${{ github.event.pull_request.head.sha }}"
pre_release_tag = f"{image_path}:{PRE_RELEASE_PREFIX}-{semver}-{head_sha}"
main_tag = f"{image_path}:{semver}"
cache_tag = f"{image_path}:cache"
main_tag_short_sha = f"{image_path}:{semver}-{head_sha[:7]}"
latest_tag = f"{image_path}:latest"
with open(os.environ['GITHUB_OUTPUT'], "a") as f:
print(f"main-tag={main_tag}", file=f)
print(f"main-tag-short-sha={main_tag_short_sha}", file=f)
print(f"latest-tag={latest_tag}", file=f)
print(f"pre-release-tag={pre_release_tag}", file=f)
- name: Add the new tags to the Docker image
run: |
pre_release_tag='${{ steps.get-new-tags.outputs.pre-release-tag }}'
main_tag='${{ steps.get-new-tags.outputs.main-tag }}'
main_tag_short_sha='${{ steps.get-new-tags.outputs.main-tag-short-sha }}'
latest_tag='${{ steps.get-new-tags.outputs.latest-tag }}'
docker pull "${pre_release_tag}"
docker tag "${pre_release_tag}" "${main_tag}"
docker tag "${pre_release_tag}" "${latest_tag}"
docker tag "${pre_release_tag}" "${main_tag_short_sha}"
docker push "${main_tag}"
docker push "${latest_tag}"
docker push "${main_tag_short_sha}"
- name: Create a GitHub release
uses: softprops/action-gh-release@v2
with:
body: ${{ github.event.pull_request.body }}
tag_name: ${{ steps.get-semver.outputs.semver }}
token: ${{ steps.get-app-token.outputs.token }}
target_commitish: ${{ github.event.pull_request.head.sha }}
- name: Merge the PR
run: gh pr merge --merge --delete-branch
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
- name: Remove git tag on failure
if: ${{ failure() }}
run: >
gh api
'repos/${{ github.repository }}/git/refs/tags/${{ steps.get-semver.outputs.semver }}'
-X DELETE
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
- name: Delete the GitHub release
if: ${{ failure() }}
run: >
gh api
'repos/${{ github.repository }}/releases/tags/${{ steps.get-semver.outputs.semver }}'
-X DELETE
env:
GH_TOKEN: ${{ steps.get-app-token.outputs.token }}
Oh, I wonder if this is because I'm using a GitHub app. My GitHub app has these permissions:
Organization Members | read Commit statuses | read + write Contents | read + write Issues | read + write Pull requests | read + write Workflows | read + write Administration | read + write Dependabot alerts | read Members | read Metadata | read Projects | read
But if it's a permission issue, then I don't understand why the gh CLI is able to update the PR
I'm having the same issue, it happens only if I trigger a second run of the same job (for example after a failure).
Same issue whilst the PR is already open
Seeing the same thing (updating a existing PR) (used v7)
Just in case this applies to some users who are experiencing this error. This same error has occurred before, and that particular case was fixed in v5 onwards. If you are using a version less than v5, please update.
At the moment I'm unable to reproduce this. Is it happening consistently? Is anyone able to create a simple example of this so that I can execute it to reproduce the error?
For v7 (peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38) the issue is reproducible whilst updating already opened PR with the same target and source branch. No issues if no PRs opened.
@iamironz Is this the commit of create-pull-request that you are using? https://github.com/peter-evans/create-pull-request/commit/153407881ec5c347639a548ade7d8ad1d6740e38
If so, that is a very old commit and doesn't contain the fix for the issue when it occurred. Please update.
I am also seeing this issue in a private forked repo. Interestingly, the PR does get updated, but the job has this error and fails which is unfortunate. It only occurs when the PR is already open. Any suggestions for work arounds?
This is now a known issue on forks with the same owner as the parent repo. I left a comment here about it: https://github.com/peter-evans/create-pull-request/pull/4064#issuecomment-3124203252
I'm planning to test the workaround for it, but I just haven't had time yet.
This is now a known issue on forks with the same owner as the parent repo. I left a comment here about it: #4064 (comment)
I'm planning to test the workaround for it, but I just haven't had time yet.
Thanks. I use the action in a couple places without issue so glad to know this only affects forks.
thank you
steps:
- uses: actions/checkout@v4
- name: Create commits
run: |
git config user.name 'Peter Evans'
git config user.email '[email protected]'
date +%s > report.txt
git commit -am "Modify tracked file during workflow"
date +%s > new-report.txt
git add -A
git commit -m "Add untracked file during workflow"
- name: Uncommitted change
run: date +%s > report.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7