diff --git a/ci/release/README.md b/ci/release/README.md new file mode 100644 index 000000000..af207b18d --- /dev/null +++ b/ci/release/README.md @@ -0,0 +1,3 @@ +# release + +Run `./release.sh --help` for instructions. diff --git a/ci/release/build.sh b/ci/release/build.sh new file mode 100755 index 000000000..5aea5df26 --- /dev/null +++ b/ci/release/build.sh @@ -0,0 +1,34 @@ +#!/bin/sh +set -eu +. "$(dirname "$0")/../../ci/sub/lib.sh" +. "$(dirname "$0")/../../ci/sub/golib.sh" +cd -- "$(dirname "$0")/../.." + +build() {( + OS="$1" + ARCH="$2" + BUILD_DIR="$BUILD_DIR/$OS/$ARCH" + + mkdir -p "$BUILD_DIR/bin" + sh_c cp LICENSE.txt "$BUILD_DIR" + sh_c "./ci/release/template/README.md.sh > $BUILD_DIR" + + export GOOS=$(goos "$OS") + export GOARCH="$ARCH" + sh_c go build -ldflags "-X lib/version.Version=$VERSION" \ + -o "$BUILD_DIR/bin/d2" ./cmd/d2 +)} + +main() { + VERSION="$(git_describe_ref)" + BUILD_DIR="ci/release/build/$VERSION" + + + runjob linux-amd64 'build linux amd64' & + runjob linux-arm64 'build linux arm64' & + runjob macos-amd64 'build macos amd64' & + runjob macos-arm64 'build macos arm64' & + wait_jobs +} + +main "$@" diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md new file mode 100644 index 000000000..1030a2961 --- /dev/null +++ b/ci/release/changelogs/next.md @@ -0,0 +1,15 @@ +## Summary 🍻 + +For v0.0.99 we focused on X, Y and Z. Enjoy! + +### Features 💸 + +- Now you can easily do x, y and z #9999 + +### Improvements 🔧 + +- Improves something or the other #9999 + +### Bugfixes 🔴 + +- Fixes something or the other #9999 diff --git a/ci/release/changelogs/template.md b/ci/release/changelogs/template.md new file mode 100644 index 000000000..501bb82d7 --- /dev/null +++ b/ci/release/changelogs/template.md @@ -0,0 +1,13 @@ +For v0.0.99 we focused on X, Y and Z. Enjoy! + +#### Features 💸 + +- Now you can easily do x, y and z #9999 + +#### Improvements 🔧 + +- Improves something or the other #9999 + +#### Bugfixes 🔴 + +- Fixes something or the other #9999 diff --git a/ci/release/release.sh b/ci/release/release.sh new file mode 100755 index 000000000..6eac14d10 --- /dev/null +++ b/ci/release/release.sh @@ -0,0 +1,125 @@ +#!/bin/sh +set -eu +cd -- "$(dirname "$0")/../.." +. ./ci/sub/lib.sh + +help() { + cat < + +$0 implements the D2 release process. + +Flags: + +--rebuild: Normally the release script will avoid rebuilding release assets if they + already exist but if you changed something and need to force rebuild, use + this flag. +--pre-release: Pass to mark the release on GitHub as a pre-release. For pre-releases the + version format should include a suffix like v0.0.99-alpha.1 + As well, for pre-releases the script will not overwrite changelogs/next.md + with changelogs/template.md and instead keep it the same as + changelogs/v0.0.99-alpha.1.md. This is because you want to maintain the + changelog entries for the eventual final release. + +Process: + +Let's say you passed in v0.0.99 as the version: + +1. It creates branch v0.0.99 based on master if one does not already exist. + - It then checks it out. +2. It moves changelogs/next.md to changelogs/v0.0.99.md if there isn't already a + changelogs/v0.0.99.md. + - If the move occured, changelogs/next.md is replaced with changelogs/template.md. As + well, a git commit with title v0.0.99 will be created. +3. It pushes branch v0.0.99 to origin. +4. It creates a v0.0.99 git tag if one does not already exist. + If one does, it ensures the v0.0.99 tag points to the current commit. + Then it pushes the tag to origin. +5. It creates a draft GitHub release for the tag if one does not already exist. +6. It updates the GitHub release notes to match changelogs/v0.0.99.md. +7. It creates a draft PR for branch v0.0.99 into master if one does not already exist. +8. It builds the release assets if they do not exist. + Pass --rebuild to force rebuilding all release assets. +9. It uploads the release assets overwriting any existing assets on the release. + +Only a draft release will be created so do not fret if something goes wrong. +You can just rerun the script again as it is fully idempotent. + +To complete the release, merge the release PR and then publish the draft release. + +Testing: + +For testing, change the origin remote to a private throwaway repository and push master to +it. Then the PR, tag and draft release will be generated against said throwaway +repository. + +Example: + $0 v0.0.99 +EOF +} + +main() { + unset FLAG \ + FLAGRAW \ + FLAGARG \ + FLAGSHIFT \ + VERSION \ + REBUILD \ + PRERELEASE + while :; do + flag_parse "$@" + case "$FLAG" in + h|help) + help + return 0 + ;; + rebuild) + flag_noarg + REBUILD=1 + shift "$FLAGSHIFT" + ;; + pre-release) + flag_noarg + PRERELEASE=1 + shift "$FLAGSHIFT" + ;; + '') + shift "$FLAGSHIFT" + break + ;; + *) + flag_errusage "unrecognized flag $FLAGRAW" + ;; + esac + done + + if [ $# -ne 1 ]; then + flag_errusage "first argument must be release version like v0.0.99" + fi + VERSION="$1" + shift + + 1_branch + 2_changelog + 3_commit + 4_tag + 5_draft_release + 6_draft_pr + 7_build_assets + 9_upload_assets + + if [ "$(git_describe_ref)" != "$TAG" ]; then + git tag -am "$TAG" "$TAG" + fi + hide git push origin "$TAG" +} + +1_branch() { + +} + +7_build_assets() { + ./ci/release/build.sh ${REBUILD:+--rebuild} $VERSION +} + +main "$@" diff --git a/ci/release/template/LICENSE.txt b/ci/release/template/LICENSE.txt new file mode 120000 index 000000000..6932c6369 --- /dev/null +++ b/ci/release/template/LICENSE.txt @@ -0,0 +1 @@ +../../../LICENSE.txt \ No newline at end of file diff --git a/ci/release/template/Makefile b/ci/release/template/Makefile new file mode 100644 index 000000000..a93267ed7 --- /dev/null +++ b/ci/release/template/Makefile @@ -0,0 +1,12 @@ +.POSIX: +.SILENT: + +PREFIX = $(DESTDIR)/usr/local + +.PHONY: install +install: + ./scripts/install.sh + +.PHONY: uninstall +uninstall: + ./scripts/uninstall.sh diff --git a/ci/release/template/README.md.sh b/ci/release/template/README.md.sh new file mode 100755 index 000000000..4f4b2e082 --- /dev/null +++ b/ci/release/template/README.md.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -eu + +cat <&2 +} + +printferr() { + COLOR=1 printfp err "$@" >&2 +} + +sh_c() { + COLOR=3 echop exec "$*" + "$@" +} + +get_rand_color() { + # 1-6 are regular and 9-14 are bright. + # 1,2 and 9,10 are red and green but we use those for success and failure. + pick "$*" 3 4 5 6 11 12 13 14 +} + +echop() {( + prefix="$1" + shift + + if [ -z "${COLOR:-}" ]; then + COLOR="$(get_rand_color "$prefix")" + fi + printf '%s: %s\n' "$(setaf "$COLOR" "$prefix")" "$*" +)} + +printfp() {( + PREFIX="$1" + shift + echop "$PREFIX" "$(printf "$@")" +)} + +hide() { + out="$(mktemp)" + set +e + "$@" >"$out" 2>&1 + code="$?" + set -e + if [ "$code" -eq 0 ]; then + return + fi + cat "$out" >&2 + exit "$code" +} + +echo_dur() { + local dur=$1 + local h=$((dur/60/60)) + local m=$((dur/60%60)) + local s=$((dur%60)) + printf '%dh%dm%ds' "$h" "$m" "$s" +} + +sponge() { + dst="$1" + tmp="$(mktemp)" + cat > "$tmp" + cat "$tmp" > "$dst" +} + +stripansi() { + # First regex gets rid of standard xterm escape sequences for controlling + # visual attributes. + # The second regex I'm not 100% sure, the reference says it selects the US + # encoding but I'm not sure why that's necessary or why it always occurs + # in tput sgr0 before the standard escape sequence. + # See tput sgr0 | xxd + sed -e $'s/\x1b\[[0-9;]*m//g' -e $'s/\x1b(.//g' +} + +runtty() { + case "$(uname)" in + Darwin) + script -q /dev/null "$@" + ;; + Linux) + script -eqc "$*" + ;; + *) + echoerr "runtty: unsupported OS $(uname)" + esac +} diff --git a/ci/release/template/uninstall.sh b/ci/release/template/uninstall.sh new file mode 100755 index 000000000..2ec6a47c1 --- /dev/null +++ b/ci/release/template/uninstall.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -eu +. "$(dirname "$0")/lib.sh" + +main() { + if [ ! -e "${PREFIX:-}" ]; then + echoerr "\$PREFIX must be set to a unix prefix directory from which to uninstall d2 like /usr/local" + exit 1 + fi + + sh_c rm -f "$PREFIX/bin/d2" +} + +main "$@" diff --git a/ci/sub b/ci/sub index 7ff838089..ffe9df3b8 160000 --- a/ci/sub +++ b/ci/sub @@ -1 +1 @@ -Subproject commit 7ff8380897435e73d53e329a7cd39dc38c7ad227 +Subproject commit ffe9df3b89e12db7f1dc4ed9d5a25730dde5cc79 diff --git a/cmd/d2/help.go b/cmd/d2/help.go index affc2abf5..961c9c275 100644 --- a/cmd/d2/help.go +++ b/cmd/d2/help.go @@ -27,7 +27,7 @@ Subcommands: %[1]s layout - Lists available layout engine options with short help %[1]s layout [layout name] - Display long help for a particular layout engine -See more docs at https://oss.terrastruct.com/d2 +See more docs and the source code at https://oss.terrastruct.com/d2 `, ms.Name, ms.FlagHelp()) }