Skip to content

Commit

Permalink
Provide script for 'automating' releases
Browse files Browse the repository at this point in the history
  • Loading branch information
cassava committed Mar 23, 2024
1 parent 2ea2bb8 commit 70ec1c6
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 5 deletions.
257 changes: 257 additions & 0 deletions .make-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
#!/bin/bash
#

# Set the colors for the terminal
cBOLD="\e[1m"
cESC="\e[0m"

cBLUE="\e[1;34m"
cRED="\e[1;31m"
cGREEN="\e[1;32m"
cWHITE="\e[1;37m"
cYELLOW="\e[1;33m"
cCYAN="\e[1;36m"
cMAGENTA="\e[1;35m"

function infof() {
local format="$1"
shift 1
printf "$cBOLD$cGREEN::$cWHITE $format$cESC\n" "$*"
}

function inputf() {
local format="$1"
shift 1
printf "$cBOLD$cBLUE<<$cWHITE $format$cESC" "$*"
}

function errorf() {
local format="$1"
shift 1
printf "$cBOLD$cRED!! Error:$cWHITE $format$cESC\n" "$*"
}

function warnf() {
local format="$1"
shift 1
printf "$cBOLD$cYELLOW// Warning:$cWHITE $format$cESC\n" "$*"
}

# -------------------------------------------------------------------------- #

release_version=$1
release_date=$(date +"%d %B, %Y")
previous_tag=$(git describe --abbrev=0)
package_dir="../repoctl.aur"
main_branch="master"
github_url="https://github.com/cassava/repoctl"

confirm() {
local prompt="$1"
inputf "$prompt"
printf " [Y/n] "
local answer
read answer
[[ "$answer" == "y" || "$answer" == "Y" || -z "$answer" ]]
}

countdown() {
local message="$1"
local seconds=$2
while [[ $seconds -ne 0 ]]; do
printf "\r%s [%s]" "$message" "$seconds"
seconds=$((seconds - 1))
sleep 1
done
printf "\r%s \n" "$message"
}

launch_editor() {
local file="$1"
local seconds=$2
countdown "-> Launching ${EDITOR}" "$seconds"
${EDITOR} "$file"
}

# Ensure working directory of repo is clean.
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
warnf "Working directory is dirty!"
echo
git status --porcelain | sed -r 's/^/\t/'
echo
confirm "Do you want to continue?" || exit 2
fi

# Get version to release interactively if necessary.
if [[ -z "$release_version" ]]; then
echo "Previous version tag: $previous_tag"
inputf "Version to release: "
read release_version
if [[ -z "$release_version" ]]; then
echo "Aborted."
exit 1
fi
fi

if [[ ! -f "$package_dir/PKGBUILD" ]]; then
warnf "AUR package directory invalid: $package_dir"
exit 1
fi

# Confirm release information.
infof "Verify release metadata"
echo "Git describe: $(git describe)"
echo "Previous version tag: $previous_tag"
echo "Release version: $release_version"
echo "Release date: $release_date"
confirm "Is this correct?" || exit 2

# Step 1:
if confirm "Update vendored dependencies?"; then
(
set -e
go get -u ./...
go mod tidy
go mod vendor
go build ./...
go build .
go test ./...
go test .

# Update .github/workflows/ci.yaml
git add vendor go.mod go.sum
git commit -m "Update dependencies"
)
fi

# Step 2:
copyright_date="2016-$(date +"%Y")"
infof "Update version.go"
sed -r \
-e "s/^(\t+Version: *\")(.*)(\",)$/\1${release_version}\3/" \
-e "s/^(\t+Date: *\")(.*)(\",)$/\1${release_date}\3/" \
-e "s/^(\t+Copyright: *\")(.*)(\",)/\1${copyright_date}\3/" \
-i version.go
countdown "-> Showing git diff version.go" 2
git diff --color=always version.go
if ! confirm "Is version.go correct?"; then
launch_editor version.go 1
fi

# Step 3:
infof "Update NEWS.md"
countdown "-> Showing git diff NEWS.md" 2
git diff --color=always NEWS.md
if confirm "Prepare NEWS.md with new section?"; then
release_notes_header="## Version ${release_version} (${release_date})"
release_commit_msgs="$(git log --format="%s" ${previous_tag}.. | sed -r 's/^/- /')"
escaped_commit_msgs="$(printf "%q" "${release_commit_msgs}")"
sed "4i${release_notes_header}\\n\\n${escaped_commit_msgs}\\n\\n"
countdown "-> Showing git diff NEWS.md" 2
git diff --color=always NEWS.md
fi
launch_editor NEWS.md 3

# Ensure project builds fine.
infof "Build repoctl"
go build ./... || exit 1
go build . || exit 1
echo "OK."

infof "Test repoctl"
go test ./... || exit 1
go test . || exit 1
echo "OK."

# Step 4:
infof "Create new commit"
git add version.go NEWS.md
countdown "-> Showing git diff --cached" 2
git diff --color=always --cached
confirm "Commit these changes?" || exit 2
git commit -m "Release version ${release_version}"

# Step 5:
infof "Create release archive"
archive_file="repoctl-${release_version}.tar.gz"
git archive --prefix="repoctl-$release_version/" -o "$package_dir/${archive_file}" HEAD
archive_md5sum=$(md5sum "$package_dir/$archive_file" | cut -d' ' -f1)

# Step 6:
infof "Patch PKGBUILD ($package_dir)"
sed -r \
-e "s/^pkgrel=.*$/pkgrel=1/" \
-e "s/^pkgver=.*$/pkgver=${release_version}/" \
-e "s/^md5sums=.*$/md5sums=('${archive_md5sum}')/" \
-i $package_dir/PKGBUILD || exit 1

infof "Generate .SRCINFO ($package_dir)"
(
cd $package_dir || exit 1
makepkg --printsrcinfo > .SRCINFO || exit 1
) || exit 1

infof "Create package ($package_dir)"
(
cd $package_dir || exit 1
makepkg || exit 1
) || exit 1

infof "Test package ($package_dir)"
(
cd $package_dir || exit 1
sudo pacman -U repoctl-${release_version}-1-x86_64.pkg.tar.zst || exit 1
expected="repoctl version ${release_version} (${release_date})"
received="$(/usr/bin/repoctl version | head -1)"
if [[ "${received}" != "${expected}" ]]; then
warnf "Unexpected repoctl version output!"
echo "-- Expected: ${expected}"
echo "-- Received: ${received}"
exit 1
fi
) || exit 1

infof "Commit changes ($package_dir)"
(
cd $package_dir || exit 1
git add PKGBUILD .SRCINFO || exit 1
countdown "-> Showing git diff --cached" 2
git diff --color=always --cached
confirm "Commit these changes?" || exit 2
git commit -m "Update repoctl to version ${release_version}" || exit 1
) || exit 1

# Step 7:
infof "Create new tag"
git tag -a v${release_version} -m "repoctl version ${release_version} release"
echo "Unpushed commits:\n"
git log --oneline --color=always $main_branch..origin/$main_branch | sed -r 's/^/\t/'
echo
confirm "Push $main_branch branch?"
git push
confirm "Push v${release_version} tag?"
git push v${release_version}

# Step 8:
infof "Create new Github release"
echo "Remember to:"
echo " - include release notes from NEWS.md"
echo " - upload the archive from $package_dir"
echo
countdown "-> Launching browser" 1
xdg-open "$github_url/releases/new"
confirm "Is the release ready?"

# Step 9:
infof "Test AUR build again"
(
set -e
cd $package_dir
git clean -xdf
makepkg

infof "Push AUR PKGBUILD"
git push
) || exit 1

infof "Release completed"
10 changes: 5 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Create a new commit with all the changes:

However, do not push this yet. The working directory should be clean.

6. Create an archive for testing.
5. Create an archive for testing.

git archive --prefix=repoctl-X.Y.Z/ -o ../repoctl.aur/repoctl-X.Y.Z.tar.gz HEAD

Expand All @@ -58,7 +58,7 @@ Create a new commit with all the changes:
If you have the rights for pushing to this, then good, otherwise you
will need to contact the owner of that package on AUR.

7. In the AUR directory, you need to update the `PKGBUILD` file, in particular
6. In the AUR directory, you need to update the `PKGBUILD` file, in particular
for the new version:

- version (set to X.Y.Z)
Expand Down Expand Up @@ -91,19 +91,19 @@ Create a new commit with all the changes:

But hold off on pushing.

8. In the main repository, create a tag, then push HEAD and tags:
7. In the main repository, create a tag, then push HEAD and tags:

git tag -a vX.Y.Z -m "repoctl version X.Y.Z release"
git push
git push --tags

9. In the Github Releases page, draft a new release.
8. In the Github Releases page, draft a new release.

- Copy the notes from `NEWS.md` into the description.
- Upload the source archive that we created in step 6.
- Create the release.

10. Back in the AUR repository for repoctl, clean the working tree and
9. Back in the AUR repository for repoctl, clean the working tree and
ensure that everything can be built cleanly from scratch:

git clean -xdf
Expand Down

0 comments on commit 70ec1c6

Please sign in to comment.