Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ outputs:
created:
description: Whether a changelog entry was created and pushed.
value: ${{ steps.create.outputs.created }}
status:
description: Whether the branch already had an entry, auto-created one, or still remains missing.
value: ${{ steps.create.outputs.status }}
message:
description: Generated changelog entry message, or empty when no entry was needed.
value: ${{ steps.create.outputs.message }}
Expand Down
48 changes: 43 additions & 5 deletions .github/actions/changelog/create-dependabot-entry/run.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail

if composer dev-tools changelog:check -- --file="${INPUT_CHANGELOG_FILE}" --against="origin/${INPUT_BASE_REF}" >/dev/null 2>&1; then
echo "created=false" >> "$GITHUB_OUTPUT"
exit 0
fi
entry_message="$(php -r 'require "vendor/autoload.php"; $resolver = new \FastForward\DevTools\Changelog\DependabotChangelogEntryMessageResolver(); echo $resolver->resolve(getenv("INPUT_PULL_REQUEST_TITLE") ?: "", (int) (getenv("INPUT_PULL_REQUEST_NUMBER") ?: 0));')"

git fetch --no-tags --depth=1 origin "+refs/heads/${INPUT_BASE_REF}:refs/remotes/origin/${INPUT_BASE_REF}"
git fetch --no-tags --depth=1 origin "+refs/heads/${INPUT_HEAD_REF}:refs/remotes/origin/${INPUT_HEAD_REF}"
git switch -C "${INPUT_HEAD_REF}" "refs/remotes/origin/${INPUT_HEAD_REF}"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

entry_message="$(php -r 'require "vendor/autoload.php"; $resolver = new \FastForward\DevTools\Changelog\DependabotChangelogEntryMessageResolver(); echo $resolver->resolve(getenv("INPUT_PULL_REQUEST_TITLE") ?: "", (int) (getenv("INPUT_PULL_REQUEST_NUMBER") ?: 0));')"
if composer dev-tools changelog:check -- --file="${INPUT_CHANGELOG_FILE}" --against="origin/${INPUT_BASE_REF}" >/dev/null 2>&1; then
{
echo "created=false"
echo "status=already-present"
printf 'message=%s\n' "${entry_message}"
} >> "$GITHUB_OUTPUT"

exit 0
fi

composer dev-tools changelog:entry -- --type=changed --file="${INPUT_CHANGELOG_FILE}" "${entry_message}"
git add "${INPUT_CHANGELOG_FILE}"

if git diff --cached --quiet -- "${INPUT_CHANGELOG_FILE}"; then
{
echo "created=false"
echo "status=missing"
printf 'message=%s\n' "${entry_message}"
} >> "$GITHUB_OUTPUT"

exit 1
fi

git commit -m "Add changelog entry for Dependabot PR #${INPUT_PULL_REQUEST_NUMBER}"
git push origin "HEAD:${INPUT_HEAD_REF}"

if ! composer dev-tools changelog:check -- --file="${INPUT_CHANGELOG_FILE}" --against="origin/${INPUT_BASE_REF}" >/dev/null 2>&1; then
{
echo "created=false"
echo "status=missing"
printf 'message=%s\n' "${entry_message}"
} >> "$GITHUB_OUTPUT"

exit 1
fi

if ! grep -F --quiet -- "- ${entry_message}" "${INPUT_CHANGELOG_FILE}"; then
{
echo "created=false"
echo "status=missing"
printf 'message=%s\n' "${entry_message}"
} >> "$GITHUB_OUTPUT"

exit 1
fi

{
echo "created=true"
echo "status=auto-created"
printf 'message=%s\n' "${entry_message}"
} >> "$GITHUB_OUTPUT"
2 changes: 1 addition & 1 deletion .github/wiki
Submodule wiki updated from 0fedf5 to 79fb0c
3 changes: 2 additions & 1 deletion .github/workflows/changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ jobs:
- Changelog file: `${{ env.CHANGELOG_FILE }}`
- Compared base ref: `origin/${{ env.BASE_REF }}`
- Dependabot fallback status: `${{ steps.dependabot_entry.outputs.status || 'not needed' }}`
- Dependabot fallback entry created: `${{ steps.dependabot_entry.outputs.created || 'false' }}`
- Dependabot fallback entry message: `${{ steps.dependabot_entry.outputs.message || 'not needed' }}`
- Dependabot fallback generated message: `${{ steps.dependabot_entry.outputs.message || 'not needed' }}`
- Validation result: success
prepare_release_pull_request:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- GitHub Actions(deps): Bump marocchino/sticky-pull-request-comment from 2 to 3 (#182)
- GitHub Actions(deps): Bump actions/github-script from 8 to 9 (#183)
- Auto-create and push minimal changelog entries for same-repository Dependabot pull requests before changelog validation reruns (#186)
- Resolve Dependabot changelog fallback state from the actual PR head branch and report `already-present`, `auto-created`, or `missing` in the workflow summary so rebased PRs cannot pass on inherited `Unreleased` entries alone (#191)

## [1.20.0] - 2026-04-23

Expand Down
53 changes: 53 additions & 0 deletions tests/Changelog/Checker/UnreleasedEntryCheckerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,59 @@ public function hasPendingChangesWillReturnTrueWhenBaselineDoesNotContainNewEntr
self::assertTrue($this->checker->hasPendingChanges(self::FILE, 'origin/main'));
}

/**
* @return void
*/
#[Test]
public function hasPendingChangesWillIgnoreEntriesOnlyInheritedFromTheBaseBranch(): void
{
$this->filesystem->readFile(self::FILE)
->willReturn('current changelog')
->shouldBeCalledOnce();
$this->parser->parse('current changelog')
->willReturn($this->createDocument([
'Auto-create and push minimal changelog entries for same-repository Dependabot pull requests before changelog validation reruns (#186)',
]))
->shouldBeCalledOnce();
$this->gitClient->show('origin/main', self::FILE, self::WORKING_DIRECTORY)
->willReturn('baseline changelog')
->shouldBeCalledOnce();
$this->parser->parse('baseline changelog')
->willReturn($this->createDocument([
'Auto-create and push minimal changelog entries for same-repository Dependabot pull requests before changelog validation reruns (#186)',
]))
->shouldBeCalledOnce();

self::assertFalse($this->checker->hasPendingChanges(self::FILE, 'origin/main'));
}

/**
* @return void
*/
#[Test]
public function hasPendingChangesWillStillDetectBranchSpecificEntriesAlongsideInheritedOnes(): void
{
$this->filesystem->readFile(self::FILE)
->willReturn('current changelog')
->shouldBeCalledOnce();
$this->parser->parse('current changelog')
->willReturn($this->createDocument([
'Auto-create and push minimal changelog entries for same-repository Dependabot pull requests before changelog validation reruns (#186)',
'GitHub Actions(deps): Bump actions/github-script from 8 to 9 (#183)',
]))
->shouldBeCalledOnce();
$this->gitClient->show('origin/main', self::FILE, self::WORKING_DIRECTORY)
->willReturn('baseline changelog')
->shouldBeCalledOnce();
$this->parser->parse('baseline changelog')
->willReturn($this->createDocument([
'Auto-create and push minimal changelog entries for same-repository Dependabot pull requests before changelog validation reruns (#186)',
]))
->shouldBeCalledOnce();

self::assertTrue($this->checker->hasPendingChanges(self::FILE, 'origin/main'));
}

/**
* @return void
*/
Expand Down
Loading