diff --git a/git-cliff-release/README.md b/git-cliff-release/README.md index 3cd3d39..9386edb 100644 --- a/git-cliff-release/README.md +++ b/git-cliff-release/README.md @@ -7,6 +7,8 @@ This action uses conventional commit history to determine the recommended versio - **release_type**: One of `auto` (default), `patch`, `minor`, `major` and `custom`. `auto` means that the version will be determined based on the commit history, `custom` will use the value of the `custom_version` input parameter, and `patch`, `minor` and `major` allow forcing the bump type. - **custom_version**: Optional unless the `release_type` is set to `custom`. - **cliff_config_path**: Path to a configuration file for git-cliff. If none is given, a built-in configuration will be used. +- **existing_changelog_path**: Path to an existing changelog. If given, the new changelog contents will be prepended to it intelligently. +- **token**: Github token to be used by github CLI (should be relevant for private repositories only) ## Outputs diff --git a/git-cliff-release/action.yaml b/git-cliff-release/action.yaml index 464e9ff..5d15d14 100644 --- a/git-cliff-release/action.yaml +++ b/git-cliff-release/action.yaml @@ -23,6 +23,16 @@ inputs: required: false type: string default: cliff.toml + existing_changelog_path: + description: Path to an existing changelog. If given, the new changelog contents will be prepended to it intelligently. + required: false + type: string + default: "" + token: + description: Github token to be used by github CLI + required: false + type: string + default: ${{ github.token }} outputs: is_prerelease: description: For convenience - was the action triggered with release_type = "prerelease"? @@ -65,8 +75,9 @@ runs: GIT_CLIFF_REPOSITORY: ${{ github.workspace }}/__release_metadata_repo GIT_CLIFF_WORKDIR: ${{ github.action_path }} GITHUB_REPO: ${{ github.repository }} - GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ inputs.token }} run: | + set -x if [[ '${{ inputs.release_type }}' = custom ]]; then version_number=$(echo ${{ inputs.custom_version }} | sed s/^v//) elif [[ '${{ inputs.release_type }}' = auto || '${{ inputs.release_type }}' = prerelease ]]; then @@ -85,9 +96,10 @@ runs: GIT_CLIFF_REPOSITORY: ${{ github.workspace }}/__release_metadata_repo GIT_CLIFF_WORKDIR: ${{ github.action_path }} GITHUB_REPO: ${{ github.repository }} - GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ inputs.token }} working-directory: ${{ github.action_path }} run: | + set -x echo 'release_notes<> $GITHUB_OUTPUT git-cliff --tag "${{ steps.version_number.outputs.tag_name }}" --unreleased --context | python enhance_context.py --repo $GITHUB_REPO --release-notes | @@ -102,22 +114,42 @@ runs: GIT_CLIFF_REPOSITORY: ${{ github.workspace }}/__release_metadata_repo GIT_CLIFF_WORKDIR: ${{ github.action_path }} GITHUB_REPO: ${{ github.repository }} - GH_TOKEN: ${{ github.token }} + GITHUB_TOKEN: ${{ inputs.token }} working-directory: ${{ github.action_path }} run: | + set -x + dump_context_args=() + enhance_context_args=() + print_changelog_args=() + + out_file=$GIT_CLIFF_WORKDIR/new_changelog.md + + if [[ -n "${{ inputs.existing_changelog_path }}" ]]; then + out_file=$GIT_CLIFF_WORKDIR/existing_changelog.md + cp "${{ github.workspace }}/${{ inputs.existing_changelog_path }}" $out_file + sed '//,//d' -i $out_file + + dump_context_args+=(--unreleased) + print_changelog_args+=(--prepend "$out_file" --unreleased) + else + print_changelog_args+=(--output "$out_file") + fi + if [[ ${{ inputs.release_type }} = prerelease ]]; then - echo 'changelog<> $GITHUB_OUTPUT - git-cliff --context | - python enhance_context.py --repo $GITHUB_REPO --unreleased-version "${{ steps.version_number.outputs.tag_name }}" | - git-cliff --from-context - >> $GITHUB_OUTPUT - echo 'EOF' >> $GITHUB_OUTPUT + enhance_context_args+=(--unreleased-version "${{ steps.version_number.outputs.tag_name }}") else - echo 'changelog<> $GITHUB_OUTPUT - git-cliff --tag "${{ steps.version_number.outputs.tag_name }}" --context | - python enhance_context.py --repo $GITHUB_REPO | - git-cliff --from-context - >> $GITHUB_OUTPUT - echo 'EOF' >> $GITHUB_OUTPUT + dump_context_args+=(--tag "${{ steps.version_number.outputs.tag_name }}") fi + + git-cliff --context "${dump_context_args[@]}" | + python enhance_context.py --repo $GITHUB_REPO "${enhance_context_args[@]}" | + git-cliff --from-context - "${print_changelog_args[@]}" + + sed -i '$a\' $out_file # Make sure there is a newline at the end of the output file + + echo 'changelog<> $GITHUB_OUTPUT + cat $out_file >> $GITHUB_OUTPUT + echo 'EOF' >> $GITHUB_OUTPUT - name: Clean up shell: bash env: diff --git a/git-cliff-release/cliff.toml b/git-cliff-release/cliff.toml index 2693f0d..512b75c 100644 --- a/git-cliff-release/cliff.toml +++ b/git-cliff-release/cliff.toml @@ -14,6 +14,8 @@ All notable changes to this project will be documented in this file.\n # template for the changelog body # https://keats.github.io/tera/docs/#introduction body = """ +{% if not version %} +{% endif %}\ {% if version and extra.release_link %}\ ## [{{ version | trim_start_matches(pat="v") }}]({{ extra.release_link }}) ({{ timestamp | date(format="%Y-%m-%d") }}) {% elif extra.unreleased_version %}\ @@ -33,7 +35,7 @@ body = """ {% else %}\ {{ commit.message | upper_first }}\ {% endif %}\ - {{" "}}([{{ commit.id | truncate(length = 7, end = "") }}]({{ commit.extra.commit_link }}))\ + {% if commit.extra.commit_link %} ([{{ commit.id | truncate(length = 7, end = "") }}]({{ commit.extra.commit_link }})){% endif %}\ {% if commit.remote.username and extra.is_release_notes %}\ {{" "}}by @{{ commit.remote.username }}\ {% elif commit.remote.username %}\ @@ -44,6 +46,8 @@ body = """ {%- endif %}\ {% endfor %} {% endfor %}\n +{% if not version %} +{% endif %}\ """ # template for the changelog footer footer = """ diff --git a/git-cliff-release/enhance_context.py b/git-cliff-release/enhance_context.py index 2f2b92d..cb96ef4 100644 --- a/git-cliff-release/enhance_context.py +++ b/git-cliff-release/enhance_context.py @@ -23,6 +23,9 @@ def load_pr_issues(owner: str, repo: str) -> dict[int, list[int]]: print(f"fetch_pr_issues.sh output: {output}") raise + if pr_issues is None: + return {} + return {int(key): value for key, value in pr_issues.items()} @@ -41,7 +44,7 @@ def enhance_release( def enhance_commit(commit: dict[str, Any], pr_issues: dict[int, list[int]]) -> None: - pr_number = commit["remote"]["pr_number"] + pr_number = commit.get("remote", {}).get("pr_number") commit["extra"] = commit["extra"] or {} commit["extra"]["commit_link"] = f"{repo_url}/commit/{commit['id']}"