From 51eafaf6df0ef62095172bbbbe0448f8d797f8ad Mon Sep 17 00:00:00 2001 From: Cody Miller Date: Fri, 4 Mar 2022 09:49:30 -0800 Subject: [PATCH] feat: refine changelog creation for releases (#51) (#53) This change refines the way changelogs are calculated. The resulting behavior is such that a release includes the commits that were made on main since the previous release was minted and any commits made on the specific release branch (such as targeted fixes or backports). Prerelease is a running log of changes made to main since the most recent release was minted. --- .github/workflows/compile-changelog.rb | 77 +++++++++++++++++++ .github/workflows/on-main-branch-change.yaml | 46 +++++++++++ .../workflows/on-release-branch-change.yml | 50 ++++++++++++ .github/workflows/on-release-created.yml | 37 +++++++++ .github/workflows/produce-branch-pdf.yml | 30 -------- .github/workflows/produce-prerelease.yaml | 29 ------- .github/workflows/produce-release-branch.yml | 17 ---- .github/workflows/produce-release-pdf.yml | 25 ------ 8 files changed, 210 insertions(+), 101 deletions(-) create mode 100644 .github/workflows/compile-changelog.rb create mode 100644 .github/workflows/on-main-branch-change.yaml create mode 100644 .github/workflows/on-release-branch-change.yml create mode 100644 .github/workflows/on-release-created.yml delete mode 100644 .github/workflows/produce-branch-pdf.yml delete mode 100644 .github/workflows/produce-prerelease.yaml delete mode 100644 .github/workflows/produce-release-branch.yml delete mode 100644 .github/workflows/produce-release-pdf.yml diff --git a/.github/workflows/compile-changelog.rb b/.github/workflows/compile-changelog.rb new file mode 100644 index 0000000..fb4e3ad --- /dev/null +++ b/.github/workflows/compile-changelog.rb @@ -0,0 +1,77 @@ + +# This script identifies the commits that have been made to the current +# branch since the release before this branch. It formats them according +# to a format specifier. +# +# Usage: +# compile-changelog outfile +# +# outfile: the file location to write the changelog to + +module Git + def self.one_line_format(repository_url) + "[%h](#{repository_url}/commit/%h) %s (%an)" + end + + def self.current_branch + `git rev-parse --abbrev-ref HEAD`.strip + end + + def self.default_branch + `git rev-parse --abbrev-ref origin/HEAD`.strip + end + + def self.default_branch_head + `git rev-parse origin/HEAD`.strip + end + + def self.initial_commit + `git rev-list --max-parents=0 #{default_branch}`.strip + end + + def self.release_branches + `git branch --list -r origin/release/*`.split("\n").map(&:strip) + end + + def self.commit_date(commit) + `git show -s --format=%ct #{commit}`.strip + end + + def self.merge_base_from(branch1, branch2) + `git merge-base #{branch1} #{branch2}`.strip + end + + # Returns the commit where the given branch forked from the default git branch. + # If the given branch is the default git branch, the branch commit is the initial + # commit in the repo. + def self.merge_base(branch) + if branch == Git::default_branch_head + Git::initial_commit() + else + Git::merge_base_from(Git::default_branch, branch) + end + end + + def self.formatted_commits_between(low, high, format) + `git log --pretty="format:#{format}" --no-merges #{low}..#{high}` + end +end + +outfile = ARGV[0] +repository_url = "https://github.com/#{ENV['GITHUB_REPOSITORY']}" +commit_upper_bound = Git::current_branch +commit_lower_bound = Git::release_branches + .map { |branch| Git::merge_base(branch) } + .reject { |commit| Git::commit_date(commit) >= Git::commit_date(commit_upper_bound) } + .sort_by { |commit| Git::commit_date(commit) } + .reverse + .first + +changelog = Git::formatted_commits_between( + commit_lower_bound || Git::initial_commit, + commit_upper_bound, + Git::one_line_format(repository_url)) + +File.open(outfile, 'a') do |file| + file.puts changelog +end diff --git a/.github/workflows/on-main-branch-change.yaml b/.github/workflows/on-main-branch-change.yaml new file mode 100644 index 0000000..0940ee4 --- /dev/null +++ b/.github/workflows/on-main-branch-change.yaml @@ -0,0 +1,46 @@ +# Creates or updates a 'prerelease' release whenever main is +# changed. Attaches a built PDF to that release. +name: On Main Branch Change +on: + push: + branches: + - main + +jobs: + build_draft_pdf: + runs-on: ubuntu-latest + steps: + - name: Set up Git repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set origin HEAD + run: git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main + + - name: Compile document + uses: xu-cheng/latex-action@v2 + with: + root_file: ifc.tex + working_directory: ltx + + - name: Compile changelog + run: | + echo 'CHANGELOG<> $GITHUB_ENV + ruby ./.github/workflows/compile-changelog.rb $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + + - name: Create prerelease + uses: ncipollo/release-action@v1 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + allowUpdates: true + name: Prerelease + prerelease: true + tag: prerelease + body: | + This release is a prerelease. The contents of this release are likely to change. + # Changelog + ${{ env.CHANGELOG }} + artifacts: | + ltx/ifc.pdf diff --git a/.github/workflows/on-release-branch-change.yml b/.github/workflows/on-release-branch-change.yml new file mode 100644 index 0000000..076952c --- /dev/null +++ b/.github/workflows/on-release-branch-change.yml @@ -0,0 +1,50 @@ +# Creates or updates a release's generated PDF when a change occurs +# to a release branch +name: On Release Branch Change +on: + push: + branches: + - "release/*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Set up Git repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set origin HEAD + run: git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main + + - name: Extract branch name + shell: bash + run: echo "RELEASE_NAME=$(echo ${GITHUB_REF#refs/heads/release/})" >> $GITHUB_ENV + + - name: Compile document + uses: xu-cheng/latex-action@v2 + with: + root_file: ifc.tex + working_directory: ltx + + - name: Compile changelog + run: | + echo 'CHANGELOG<> $GITHUB_ENV + ruby ./.github/workflows/compile-changelog.rb $GITHUB_ENV + echo 'EOF' >> $GITHUB_ENV + + - name: Update release + uses: ncipollo/release-action@v1 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + allowUpdates: true + name: ${{ env.RELEASE_NAME }} + prerelease: false + tag: ${{ env.RELEASE_NAME }} + body: | + # Changelog + ${{ env.CHANGELOG }} + artifacts: | + ltx/ifc.pdf + diff --git a/.github/workflows/on-release-created.yml b/.github/workflows/on-release-created.yml new file mode 100644 index 0000000..3caf7e0 --- /dev/null +++ b/.github/workflows/on-release-created.yml @@ -0,0 +1,37 @@ +# Creates a release branch whenever a release is created. + +name: On Release Created +on: + release: + types: + - published + +jobs: + create_branch: + runs-on: ubuntu-latest + steps: + - uses: peterjgrainger/action-create-branch@v2.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + branch: 'release/${{ github.event.release.tag_name }}' + + build_latex: + runs-on: ubuntu-latest + steps: + - name: Set up Git repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Compile document + uses: xu-cheng/latex-action@v2 + with: + root_file: ifc.tex + working_directory: ltx + + - name: Add PDF to Release + uses: softprops/action-gh-release@v0.1.13 + if: startsWith(github.ref, 'refs/tags/') + with: + files: ltx/ifc.pdf diff --git a/.github/workflows/produce-branch-pdf.yml b/.github/workflows/produce-branch-pdf.yml deleted file mode 100644 index b3e11a6..0000000 --- a/.github/workflows/produce-branch-pdf.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Creates or updates a release's generated PDF when a change occurs -# to a release branch -name: Update Existing Release -on: - push: - branches: - - "release/*" - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Set up Git repository - uses: actions/checkout@v2 - - name: Extract branch name - shell: bash - run: echo "RELEASE_NAME=$(echo ${GITHUB_REF#refs/heads/release/})" >> $GITHUB_ENV - - name: Compile document - uses: xu-cheng/latex-action@v2 - with: - root_file: ifc.tex - working_directory: ltx - - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: ${{env.RELEASE_NAME}} - prerelease: false - title: ${{env.RELEASE_NAME}} - files: ltx/ifc.pdf \ No newline at end of file diff --git a/.github/workflows/produce-prerelease.yaml b/.github/workflows/produce-prerelease.yaml deleted file mode 100644 index 8cde05b..0000000 --- a/.github/workflows/produce-prerelease.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Creates or updates a 'prerelease' release whenever main is -# changed. Attaches a built PDF to that release. -name: Create prerelease PDF -on: - push: - branches: - - main - -jobs: - build_draft_pdf: - runs-on: ubuntu-latest - steps: - - name: Set up Git repository - uses: actions/checkout@v2 - - name: Compile document - uses: xu-cheng/latex-action@v2 - with: - root_file: ifc.tex - working_directory: ltx - - - name: Create prerelease - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "prerelease" - prerelease: true - title: "Prerelease" - files: | - ltx/ifc.pdf \ No newline at end of file diff --git a/.github/workflows/produce-release-branch.yml b/.github/workflows/produce-release-branch.yml deleted file mode 100644 index af6dc40..0000000 --- a/.github/workflows/produce-release-branch.yml +++ /dev/null @@ -1,17 +0,0 @@ -# Creates a release branch whenever a release is created. - -name: Create Release Branch -on: - release: - types: - - published - -jobs: - create_branch: - runs-on: ubuntu-latest - steps: - - uses: peterjgrainger/action-create-branch@v2.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - branch: 'release/${{ github.event.release.tag_name }}' diff --git a/.github/workflows/produce-release-pdf.yml b/.github/workflows/produce-release-pdf.yml deleted file mode 100644 index c3d7fd6..0000000 --- a/.github/workflows/produce-release-pdf.yml +++ /dev/null @@ -1,25 +0,0 @@ -# Builds a PDF of the IFC spec and attaches it to any release that -# is created. - -name: Attach PDF to Release -on: - release: - types: - - published - -jobs: - build_latex: - runs-on: ubuntu-latest - steps: - - name: Set up Git repository - uses: actions/checkout@v2 - - name: Compile document - uses: xu-cheng/latex-action@v2 - with: - root_file: ifc.tex - working_directory: ltx - - name: Add PDF to Release - uses: softprops/action-gh-release@v0.1.13 - if: startsWith(github.ref, 'refs/tags/') - with: - files: ltx/ifc.pdf \ No newline at end of file