Adding a dump example #73
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Changelog Checks | |
on: | |
pull_request: | |
branches: main | |
types: | |
- opened | |
- synchronize | |
- reopened | |
- ready_for_review | |
jobs: | |
Check-Changelog-Project-Versions: | |
name: Validate | |
runs-on: ubuntu-latest | |
if: >- | |
! github.event.pull_request.draft | |
steps: | |
# Gather Pull Request Change Information | |
- id: change-check | |
shell: bash | |
env: | |
GH_TOKEN: ${{ github.token }} | |
run: >- | |
gh --repo ${{ github.event.pull_request.base.repo.full_name }} | |
pr view --json files --jq ' | |
.files | map( .path ) | | |
"changelog-changed=\( any( . == "CHANGELOG.md" ) )", | |
"source-changed=\( any( | |
. == "LICENSE" | |
or . == "README.md" | |
or . == "pyproject.toml" | |
or startswith( "src/" ) | |
) )" | |
' ${{ github.event.pull_request.number }} | |
>> "$GITHUB_OUTPUT" | |
# Checkout Applicable Source Code | |
- uses: actions/checkout@v3 | |
with: | |
repository: ${{ github.event.pull_request.head.repo.full_name }} | |
ref: ${{ github.event.pull_request.head.ref }} | |
path: head | |
- uses: actions/checkout@v3 | |
with: | |
repository: ${{ github.event.pull_request.base.repo.full_name }} | |
ref: ${{ github.event.pull_request.base.ref }} | |
path: base | |
sparse-checkout: CHANGELOG.md | |
# Run Checks to Ensure Changelog is Managed Correctly | |
- uses: actions/setup-python@v4 | |
with: | |
python-version: '3.11' | |
- shell: bash | |
run: pip install ./head | |
- shell: python | |
env: | |
SOURCE_CHANGED: ${{ steps.change-check.outputs.source-changed }} | |
CHANGELOG_CHANGED: ${{ steps.change-check.outputs.changelog-changed }} | |
run: |- | |
import changelog, semver, sys, os | |
from typing import Sequence | |
def error( | |
msg: str, | |
*, | |
title: str | None = None, | |
file: str | None = None, | |
line: int | None = None, | |
col: int | None = None, | |
exit: bool = True | |
): | |
details = ",".join( ( f'{ key }={ value }' for key, value in { | |
"title": title, | |
"file": file, | |
"line": line, | |
"col": col | |
}.items() if value is not None ) ) | |
print( | |
f'::error{ ( " " + details ) if details else "" }::{ msg }', | |
flush = True, | |
file = sys.stderr | |
) | |
if exit: | |
sys.exit( 1 ) | |
def main( cli_args: Sequence[ str ] )-> None: | |
try: | |
with open( "head/CHANGELOG.md", "r" ) as fp: | |
head_changes = changelog.load( fp ) | |
except changelog.ChangelogParsingError as e: | |
error( msg = str( e ), file = "CHANGELOG.md", line = e.line_number, col = e.column_number ) | |
try: | |
with open( "base/CHANGELOG.md", "r" ) as fp: | |
base_changes = changelog.load( fp ) | |
except Exception as e: | |
error( msg = f'{ type( e ).__name__ }: { e }', title = 'Error Loading "CHANGELOG.md" from Base' ) | |
if not head_changes: | |
error( | |
'A change entry is required in "CHANGELOG.md"', | |
title = "No Changelog Entry Found" | |
) | |
if any( not isinstance( change[ "version" ], semver.Version ) for change in head_changes ): | |
error( | |
'A version in "CHANGELOG.md" is "Unreleased", which cannot be merged', | |
title = 'Unreleased" Version Invalid' | |
) | |
if any( change[ "date" ] is None for change in head_changes ): | |
error( | |
'At least one record in "CHANGELOG.md" is missing a date', | |
title = 'Record Missing Date' | |
) | |
if head_changes[ 0 ][ "version" ] != semver.Version.parse( changelog.__version__ ): | |
error( | |
'Project version and latest version in "CHANGELOG.md" do not match', | |
title = 'Version Mismatch' | |
) | |
if os.environ[ "SOURCE_CHANGED" ] == 'true' and 1 < len( head_changes ): | |
last_version = head_changes[ 1 ][ "version" ] | |
incremented = ( last_version.bump_major(), last_version.bump_minor(), last_version.bump_patch() ) | |
if head_changes[ 0 ][ "version" ] not in incremented: | |
error( | |
f'Latest "CHANGELOG.md" version, "{ head_changes[ 0 ][ "version" ] }", is not a major, minor,' | |
' or patch incrementation of the previous version, "{ head_changes[ ` ][ "version" ] }"', | |
title = '"CHANGELOG.md" Version Not Incremented' | |
) | |
if os.environ[ "SOURCE_CHANGED" ] == 'false' and os.environ[ "CHANGELOG_CHANGED" ] == 'true': | |
error( | |
'New changes should only be added to "CHANGELOG.md" if source code is updated', | |
title = '"CHANGELOG.md" Version Should Not Be Incremented' | |
) | |
if base_changes: | |
to_check = head_changes[ 1 if os.environ[ "SOURCE_CHANGED" ] == 'true' else 0 : ] | |
if ( [ change[ "version" ] for change in to_check ] | |
!= [ change[ "version" ] for change in base_changes ] | |
): | |
error( | |
'Previously released changelog versions are immutable', | |
title = "Previously Released Version Changed" | |
) | |
if __name__ == '__main__': | |
main( sys.argv[ 1 : ] ) |