Skip to content

Commit

Permalink
new: release/ (close #72, Release bot)
Browse files Browse the repository at this point in the history
  • Loading branch information
tfiers committed Jan 27, 2023
1 parent 14c43a0 commit 7d95c8f
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 54 deletions.
46 changes: 0 additions & 46 deletions .github/workflows/TagBot.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/docs/localdev/Manifest.toml
/test/standalone/Manifest.toml
/local
/release/Manifest.toml
11 changes: 3 additions & 8 deletions docs/src/devguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@
## Releasing a new version

#### The release commit:
- In [`Project.toml`], remove the `-dev` suffix from `version`.
- Roll-over [`Changelog.md`]:
- Add a commented-out section above the new release, for the next
version.
- Move the 'unreleased' badge to the commented out section. Replace with a new
'released' badge and link, in analogy with previously released versions.
- Commit the above, and comment on this commit on GitHub
with `@JuliaRegistrator register`. (This opens a PR in the General registry)
See the readme in [`release/`].

[`release`]: https://github.com/tfiers/PkgGraph.jl/tree/main/release#readme

#### In the next commit:
- In [`Project.toml`], bump the relevant version component, and add `-dev` again.
Expand Down
8 changes: 8 additions & 0 deletions release/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[deps]
Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
DefaultApplication = "3f0dd361-4fe0-5fc6-8523-80b14ec94d85"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
27 changes: 27 additions & 0 deletions release/ReadMe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Release script

To release a new version of PkgGraph.jl, run
```
julia release.jl
```
..and follow the steps shown.

This script will:
- In `Project.toml`, remove the `-dev` suffix from `version`
- Roll-over `Changelog.md`:
- Add a commented-out section above the new release, for the next
version
- Move the 'unreleased' badge to the commented out section. Replace
with a new 'released' badge and link
- Commit the above, and have you comment on this commit on GitHub with
`@JuliaRegistrator register`. (This opens a PR in the General
registry)
- Draft a GitHub release

## Requirements

- The [GitHub CLI] (`gh`) must be installed and available on your path,
and you've run `gh auth login`
- `]activate release` and `]instantiate`

[GitHub CLI]: https://github.com/cli/cli
67 changes: 67 additions & 0 deletions release/changelog.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@

# Step 2: Rollover Changelog.md
# -----------------------------

changelog_file = "Changelog.md"
changelog = read(changelog_file, String)

shorthand(version) = begin
(; major, minor, patch) = VersionNumber(version)
if minor == 0 && patch == 0
"v$major"
elseif patch == 0
"v$major.$minor"
else
"v$major.$minor.$patch"
end
end
v_short = shorthand(version_to_release)

unreleased_header(version) = """
<br>
## $version &nbsp;<sub>[![][unreleased-badge]][devlink]</sub>
[unreleased-badge]: https://img.shields.io/badge/Unreleased-orange
[devlink]: https://github.com/$ghrepo#development
"""

released_header(version, datestr = date_for_badge()) = """
<br>
## $version &nbsp;<sub>[![][$version-date-badge]][$version-release]</sub>
[$version-date-badge]: https://img.shields.io/badge/Released_on-$datestr-blue
[$version-release]: https://github.com/$ghrepo/releases/tag/$version
"""
date_for_badge() = Dates.format(now(), "yyyy--mm--dd")

# (Could prompt for new dev version here)
# prompt("""What is the new dev version number? (eg: "v0.9", "v1.2.1")""")
# (Then parse, w/ VersionNumber, which handles both "1" and "v1";
# and display back to user (shorthand :)).

old_header = unreleased_header(v_short)
new_headers = """
<!--
$(unreleased_header("v…"))
_{no changes yet}_
-->
$(released_header(v_short))
"""
println("Reading [$changelog_file]")
println("Looking for 'unreleased header' for \"", blue(v_short), "\"")
if findfirst(old_header, changelog) == nothing
println("Header not found. We won't edit the Changelog")
else
println("Header found. Will update to a 'released' header, and add a"
* " commented-out section above it for the future dev version.")
confirm_or_quit("Continue?")
new_changelog = replace(changelog, old_header=>new_headers)
!dryrun && write(changelog_file, new_changelog)
println("Updated [$changelog_file]")
end
println()
27 changes: 27 additions & 0 deletions release/commit.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

# Step 3: Commit
# --------------

println("Will commit [$projectfile] and [$changelog_file]")
println("You can check the changes to be committed in e.g. VS Code")
confirm_or_quit("Stage and commit?")
!dryrun && add!(repo, projectfile)
!dryrun && add!(repo, changelog_file)
msg = "Set version to `$version_to_release`"
if dryrun
short_sha = "abc1234"
else
sha = commit(repo, msg)
short_sha = string(sha)[1:7]
end
println("Made commit ", blue(short_sha), " (\"$msg\")")
confirm_or_quit("Push?")
!dryrun && push(repo)
commit_url = "https://github.com/$ghrepo/commits/$short_sha"
println("Commit pushed. Url: ", blue(commit_url))
magic_phrase = "@JuliaRegistrator register"
println("Magic phrase: \"$magic_phrase\"")
confirm_or_quit("Copy phrase to clipboard, and open browser to commit url?")
!dryrun && clipboard(magic_phrase)
!dryrun && DefaultApplication.open(commit_url)
println()
74 changes: 74 additions & 0 deletions release/gh_release_draft.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Step 4: Draft gh release
# ------------------------

print("Creating gh release draft … ")

get_string(url) = String(take!(Downloads.download(url, IOBuffer())))
get_json(url) = JSON.parse(get_string(url))

baseurl = "https://api.github.com/repos/$ghrepo"
last_release_url = "$baseurl/releases/latest"
last_release_date = get_json(last_release_url)["published_at"]

issue_url = ("$baseurl/issues?state=closed"
* "&since=$last_release_date&per_page=100"
* "&sort=created&direction=asc" # Oldest first
)
# ↪ Current limitation: no more than 100 closed issues (no multipage)
issues_list = get_json(issue_url)
closed_issues = []
merged_PRs = []
for issue_obj in issues_list
title = issue_obj["title"]
author = issue_obj["user"]["login"]
nr = issue_obj["number"]
if "pull_request" in keys(issue_obj)
push!(merged_PRs, (; title, nr, author))
else
push!(closed_issues, (; title, nr))
end
end
release_body = """
Human-written changelog: [**Changelog @ $v_short**][cl]
[cl]: https://github.com/$ghrepo/blob/main/$changelog_file#$v_short--
"""
if !isempty(merged_PRs)
PR_line(; title, nr, author) = " - $title (#$nr) ($author)"
PR_lines = [PR_line(; PR...) for PR in merged_PRs]
PR_list = join(PR_lines, "\n")
release_body *= """
Merged PRs:
- <details><summary><sub>[Click to expand]</sub></summary>
$PR_list
</details>
"""
end
if !isempty(closed_issues)
issue_line(; title, nr) = " - $title (#$nr)"
issue_lines = [issue_line(; iss...) for iss in closed_issues]
issue_list = join(issue_lines, "\n")
release_body *= """
Closed issues:
- <details><summary><sub>[Click to expand]</sub></summary>
$issue_list
</details>
"""
end

cmd = `gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
/repos/$ghrepo/releases \
-f tag_name='$v_short' \
-f body='$release_body' \
-F draft=true`

println("done")
confirm_or_quit("Send release draft to GitHub and open in browser?")
!dryrun && run(cmd)
DefaultApplication.open("https://github.com/$ghrepo/releases")
29 changes: 29 additions & 0 deletions release/projecttoml.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Step 1: Project.toml: remove `-dev` from version
# ------------------------------------------------

projectfile = "Project.toml"
text = read(projectfile, String)
# Matches a line like `version = "…"`, but w/ arbitrary whitespace.
version_line_pattern = r"^\s*version\s*=\s*\"(.*)\"\s*$"m
m = match(version_line_pattern, text)
matched_line = m.match
current_version = m.captures[1] # `v0.6.0-dev`, eg
version_to_release = first(split(current_version, "-"))
# ↪ Could instead do `VersionNumber(current_version)`, and use its
# `.prerelease` field, which for the above example is `("dev",)`.
# https://docs.julialang.org/en/v1/manual/strings/#man-version-number-literals

println("Reading [$projectfile]")
println("Current version: ", blue(current_version))
println("Version to release: ", blue(version_to_release))
if current_version == version_to_release
println("These version are the same. (No '-dev' suffix found)")
println("We won't edit Project.toml")
else
confirm_or_quit("Update Project.toml?")
new_line = replace(matched_line, current_version=>version_to_release)
new_text = replace(text, matched_line=>new_line)
!dryrun && write(projectfile, new_text)
println("Updated [$projectfile] to $version_to_release")
end
println()
45 changes: 45 additions & 0 deletions release/release.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

using Pkg
Pkg.activate(@__DIR__)

using Base: prompt
using Pkg
using Dates
using LibGit2: GitRepo, isdirty, add!, commit, push
using Crayons
using DefaultApplication
using Downloads
using JSON

ghrepo = "tfiers/PkgGraph.jl"
dryrun = false

dryrun && @info "Dry run"
println()

blue = Crayon(foreground=:blue)

reporoot = dirname(@__DIR__)
cd(reporoot)
println("Working directory: ", blue(pwd()))
println()

function confirm_or_quit(question)
answer = prompt(question * " [Y/n]")
lowercase(answer) in ["", "y"] || (println("Goodbye"); exit())
end

repo = GitRepo(".")
if isdirty(repo)
println("There are uncommitted changes")
# println("Please commit first, then run this script again")
# exit()
println()
end

include("projecttoml.jl")
include("changelog.jl")
include("commit.jl")
include("gh_release_draft.jl")

println("Done")

0 comments on commit 7d95c8f

Please sign in to comment.