diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md new file mode 100755 index 0000000..389e978 --- /dev/null +++ b/.chglog/CHANGELOG.tpl.md @@ -0,0 +1,49 @@ +{{ if .Versions -}} + +## [Unreleased] + +{{ if .Unreleased.CommitGroups -}} +{{ range .Unreleased.CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{ range .Versions }} + +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} +{{ range .CommitGroups -}} +### {{ .Title }} +{{ range .Commits -}} +- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end }} +{{ end -}} + +{{- if .RevertCommits -}} +### Reverts +{{ range .RevertCommits -}} +- {{ .Revert.Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +### {{ .Title }} +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{- if .Versions }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ range .Versions -}} +{{ if .Tag.Previous -}} +[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} +{{ end -}} +{{ end -}} +{{ end -}} \ No newline at end of file diff --git a/.chglog/config.yml b/.chglog/config.yml new file mode 100755 index 0000000..a498033 --- /dev/null +++ b/.chglog/config.yml @@ -0,0 +1,43 @@ +style: github +template: CHANGELOG.tpl.md +info: + title: CHANGELOG + repository_url: https://github.com/grafana/grafana-build-tools +options: + tag_filter_pattern: '^v' + sort: "date" + + header: + # The format for the subject line: `: ` + # The list of recognized types is specified below. + pattern: "^(\\w*)\\:\\s(.*)$" + pattern_maps: + - Type + - Subject + + commits: + filters: + Type: # types to include in changelog, anything else is not added + - feat + - fix + - perf + + commit_groups: + group_by: Type + title_maps: # How to present types in the changelog + feat: Features + fix: Bug Fixes + perf: Performance Improvements + + issues: + prefix: + - '#' + + refs: + actions: + - Closes + - Fixes + + notes: + keywords: + - BREAKING CHANGE diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/Dockerfile b/Dockerfile index 89dc84b..9177d40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,6 +50,9 @@ FROM registry.hub.docker.com/library/golang:1.21.3 as go-build # Add shellcheck COPY --from=registry.hub.docker.com/koalaman/shellcheck:v0.9.0 /bin/shellcheck /build + # Add git-chglog + RUN env GOBIN=/build go install github.com/git-chglog/git-chglog/cmd/git-chglog@v0.15.4 + FROM registry.hub.docker.com/library/debian:stable-slim as build COPY --from=go-build /usr/local/go /usr/local/go diff --git a/Makefile b/Makefile index 479d964..3c020a8 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,11 @@ S := @ ROOTDIR := $(abspath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) IMAGE_REPO := ghcr.io/grafana -IMAGE_NAME := build-tools +IMAGE_NAME := grafana-build-tools IMAGE_TAG ?= $(shell $(ROOTDIR)/scripts/image-tag) IMAGE := $(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) LATEST_IMAGE := $(IMAGE_REPO)/$(IMAGE_NAME):latest +LOCAL_IMAGE := $(IMAGE_REPO)/$(IMAGE_NAME):local LOCAL_ARCH := $(strip $(shell $(ROOTDIR)/scripts/local-machine)) @@ -36,6 +37,12 @@ endef $(foreach BUILD_ARCH,$(PUSH_ARCHES),$(eval $(call build-target,$(BUILD_ARCH)))) +.PHONY: build-local +build-local: + docker build . -f Dockerfile -t "$(LOCAL_IMAGE)" + +BUILD_TARGETS += build-local + .PHONY: build build: $(BUILD_TARGETS) build: ## build the image diff --git a/lib/image-test b/lib/image-test index f143f27..5a484ea 100755 --- a/lib/image-test +++ b/lib/image-test @@ -54,6 +54,9 @@ golangci-lint version echo '=== shellcheck' shellcheck --version +echo '=== git-chglog' +git-chglog --help + echo '=== gcc' gcc --version diff --git a/scripts/release b/scripts/release new file mode 100755 index 0000000..a2be58d --- /dev/null +++ b/scripts/release @@ -0,0 +1,140 @@ +#!/bin/sh + +set -e +set -u + +gbt_image=ghcr.io/grafana/grafana-build-tools:local + +for req in git docker ; do + if ! command -v "${req}" > /dev/null 2>&1 ; then + echo "E: '${req}' is needed to run this script. Abort." + exit 1 + fi +done + +next_version=${1:-} + +cd "$(git rev-parse --show-toplevel)" || exit 2 + +if test ! -e CHANGELOG.md ; then + echo "E: Expecting a CHANGELOG.md file in $PWD, none found. Abort." + exit 3 +fi + +current_version() { + git describe --tags HEAD | cut -d- -f1 | tr -d v +} + +next_version_patch() { + parts=$(current_version) + major=$(echo "${parts}" | cut -d. -f1) + minor=$(echo "${parts}" | cut -d. -f2) + patch=$(echo "${parts}" | cut -d. -f3) + echo "${major}.${minor}.$((patch+1))" +} + +next_version_minor() { + parts=$(current_version) + major=$(echo "${parts}" | cut -d. -f1) + minor=$(echo "${parts}" | cut -d. -f2) + echo "${major}.$((minor+1)).0" +} + +next_version_major() { + parts=$(current_version) + major=$(echo "${parts}" | cut -d. -f1) + echo "$((major+1)).0.0" +} + +# Does the most recent commit look like a release? +head_is_release=false +git log --format=%s --max-count=1 | grep -q -E "^Release v[0-9]+\.[0-9]+\.[0-9]+( \(#[0-9]+\))?\$" && head_is_release=true + +if test "${head_is_release}" = false -a -z "${next_version}" ; then + cv=$(current_version) + next_patch=$(next_version_patch) + next_minor=$(next_version_minor) + next_major=$(next_version_major) + cat <<-EOT + I: Current version: v${cv} + I: Next fix: v${next_patch} + I: Next feature: v${next_minor} + I: Next breaking change: v${next_major} + + I: Changes since current version: + + EOT + + git --no-pager log --pretty=tformat:' %C(auto)%h %d %s' "v${cv}...HEAD" + + cat <<-EOT + + E: Next version argument required. Abort. + EOT + exit 4 +fi + +commit_msg=$(mktemp) + +cleanup() { + rm -f "${commit_msg}" +} + +trap cleanup EXIT + +if ${head_is_release} ; then + # We have a release, tag it. + + # First extract the version from the most recent commit. We know we + # have this because we tested for it above. + next_version=$(git log --format=%s --max-count=1 | sed -e 's,^Release \(\S\+\).*,\1,') + + if test -z "${next_version}" ; then + echo 'E: Unexpected condition looking for the next version. Abort.' + exit 127 + fi + + # Then extract the commit message from the most recent commit. + git show --pretty=format:"%B" --no-patch > "${commit_msg}" + + # Then create a tag with the next version. + git tag --annotate --file="${commit_msg}" "${next_version}" + + cat <<-EOT + An annotated tag has been created for version ${next_version}. + + You must push this tag to the remote repository in order to trigger the + release process. + EOT +else + # Need to create release notes. + cur_version=$(git describe --tags | cut -d- -f1) + + if ! docker image inspect "${gbt_image}" > /dev/null 2>&1 ; then + make build-local + fi + + docker run --rm --user "$(id -u):$(id -g)" -v "$PWD:/work" --workdir /work "${gbt_image}" \ + git chglog --next-tag "${next_version}" > CHANGELOG.md + + git add CHANGELOG.md + + git switch --create "release-${next_version}" + + cat > "${commit_msg}" <<-EOT + Release ${next_version} + + $(git log --oneline --reverse "${cur_version}".. | cut -d' ' -f2- | sed -e 's,^,* ,') + EOT + + git commit --signoff --file="${commit_msg}" + + cat <<-EOT + + A commit has been created to update the CHANGELOG.md file and prepare a + release for version ${next_version}. + + Please open a PR and once that is merged, run this script again with the + same version number as argument. + EOT +fi