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
81 changes: 38 additions & 43 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,54 @@
# publishes to nuget if the version number in PrettyPrompt.csproj changes

name: publish to nuget
# On pushing a tag like v5.0.1, publish to nuget.org and create a GitHub release.
# Use publish-release.ps1 to push a release.
name: release

on:
push:
branches:
- main

tags:
- "v[0-9]+.*" # not a regex! ".*" means a period followed by any character https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet

permissions:
contents: write # needed to create the GitHub release

jobs:
build:

runs-on: windows-latest

steps:
- uses: actions/checkout@v1

- name: Check for new version
id: CheckReleaseRequired
shell: pwsh
run: |
$publishedversions = (Find-Package -AllVersions -AllowPrereleaseVersions -Name "PrettyPrompt").Version
echo "Found published versions: $publishedversions"
if ($publishedversions.Count -gt 0) {
$csproj = [xml](Get-Content ./src/PrettyPrompt/PrettyPrompt.csproj)
$localversion = $csproj.Project.PropertyGroup.Version[0]
echo "Version in the repository is $localversion"
$isReleaseRequired = (-not $publishedversions.Contains($localversion)).ToString().ToLower()
echo "Release required: $isReleaseRequired"
echo "::set-output name=LOCAL_VERSION::v$localversion"
echo "::set-output name=IS_RELEASE_REQUIRED::$isReleaseRequired"
}

- uses: actions/checkout@v4

- name: Install Dotnet
uses: actions/setup-dotnet@v1
if: steps.CheckReleaseRequired.outputs.IS_RELEASE_REQUIRED == 'true'
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
10.0.x
dotnet-version: '10.0.x'

- name: Create NuGet Package
if: steps.CheckReleaseRequired.outputs.IS_RELEASE_REQUIRED == 'true'
- name: Dotnet Installation Info
run: dotnet --info

- name: Pack
run: dotnet pack ./src/PrettyPrompt/PrettyPrompt.csproj -c Release -p:ContinuousIntegrationBuild=true

- name: Publish to NuGet
if: steps.CheckReleaseRequired.outputs.IS_RELEASE_REQUIRED == 'true'
run: dotnet nuget push --skip-duplicate --api-key ${{secrets.NUGET_API_KEY}} --source 'https://api.nuget.org/v3/index.json' .\src\PrettyPrompt\bin\Release\PrettyPrompt.*.nupkg
run: dotnet nuget push --skip-duplicate --api-key ${{ secrets.NUGET_API_KEY }} --source 'https://api.nuget.org/v3/index.json' .\src\PrettyPrompt\bin\Release\PrettyPrompt.*.nupkg

- name: Create Git Tag
if: steps.CheckReleaseRequired.outputs.IS_RELEASE_REQUIRED == 'true'
uses: actions/github-script@v6
with:
script: |
github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/tags/${{ steps.CheckReleaseRequired.outputs.LOCAL_VERSION }}',
sha: context.sha
})
# Pull the notes for this version straight out of CHANGELOG.md so the GitHub release
# mirrors what's already curated there (CHANGELOG.md is the single source of truth).
- name: Extract release notes from CHANGELOG
shell: pwsh
run: |
$version = '${{ github.ref_name }}'.TrimStart('v')
$changelog = Get-Content -Raw CHANGELOG.md
$escaped = [regex]::Escape($version)
$match = [regex]::Match($changelog, "(?ms)^# Release $escaped[ \t]*\r?\n(.*?)(?=\r?\n# Release |\z)")
if (-not $match.Success) {
Write-Error "Could not find a '# Release $version' section in CHANGELOG.md"
exit 1
}
Set-Content -Path release-notes.md -Value $match.Groups[1].Value.Trim()

- name: Create GitHub release
shell: pwsh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create "${{ github.ref_name }}" --title "${{ github.ref_name }}" --notes-file release-notes.md --verify-tag
20 changes: 15 additions & 5 deletions PublishRelease.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@

If you want to make a new release of PrettyPrompt:

- Pull the latest `main` branch.
- Increment the version in PrettyPrompt.csproj
- Update the release notes
- Make a pull request against `main`
1. Pull the latest `main` branch.
2. Increment the `<Version>` in `src/PrettyPrompt/PrettyPrompt.csproj`.
3. Add a `# Release <version>` section to the top of `CHANGELOG.md` describing the changes.
4. Make a pull request with the above, and merge it into `main`.
5. From an up-to-date `main`, run `./publish-release.ps1`.

The GitHub action will handle the rest -- it will read the version from the csproj, publish and build to nuget, and create a git tag automatically.
The script verifies your checkout is clean and up to date, reads the version from the csproj,
and (after a confirmation prompt) creates and pushes a `v<version>` git tag.

Pushing the tag triggers `.github/workflows/release.yml`, which:

- builds and pushes the NuGet package to nuget.org, and
- creates a GitHub release for the tag, using the matching `# Release <version>` section of
`CHANGELOG.md` as the release notes.

Nothing is published until you push the tag, so bumping the version in a PR is safe on its own.
23 changes: 23 additions & 0 deletions publish-release.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
$localChanges = git status --short
if ( $null -ne $localChanges ) {
Write-Output "Uncommitted changes detected, aborting release."
Exit 1
}

git fetch origin
$remoteChanges = git log HEAD..origin/main --oneline
if ( $null -ne $remoteChanges ) {
Write-Output "The main branch is out of date, aborting release."
Exit 2
}

$csproj = [xml](Get-Content ./src/PrettyPrompt/PrettyPrompt.csproj)
# Select the <Version> node directly. Using xpath allows the project to have more than one <PropertyGroup>
$version = $csproj.SelectSingleNode('//Project/PropertyGroup/Version').InnerText.Trim()

Write-Output "Reminder: Did you update the CHANGELOG.md with a '# Release $version' section?"
Write-Output "Press Enter to create tag ""v$version"" and publish to nuget.org"
Read-Host

git tag "v$version"
git push origin "v$version"
Loading