Skip to content

Commit

Permalink
Merge pull request #668 from oasisprotocol/mz/punch
Browse files Browse the repository at this point in the history
Use Punch tool for tracking and bumping project's version
  • Loading branch information
buberdds authored Mar 24, 2024
2 parents 12c4f8d + c227601 commit 4f00f86
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .changelog/668.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Use [Punch] tool for tracking and bumping project's version

[Punch]: https://github.com/lgiordani/punch
2 changes: 2 additions & 0 deletions .github/workflows/ci-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
branches:
- main
paths-ignore: # Do not trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md
# Or when a pull request event occurs for a pull request against one of the
Expand All @@ -16,6 +17,7 @@ on:
branches:
- main
paths-ignore: # Do not trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
branches:
- main
paths-ignore: # Do not trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md
# Or when a pull request event occurs for a pull request against one of the
Expand All @@ -16,6 +17,7 @@ on:
branches:
- main
paths-ignore: # Do not trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md

Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker-nexus.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
branches:
- main
paths-ignore: # Do not trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md
workflow_dispatch: # manual; for debugging workflow before merging branch into `main`
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/prepare-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: mock # This name appears in GitHub's Checks API and in workflow's status b
# However, our branch protection rules still require that the jobs in those
# workflows _pass_; them being skipped is not good enough for Github.
#
# This workflow creates mock success statuses for all the jobs that would
# This workflow creates mock success statuses for all the jobs that would
# otherwise run in regular CI workflows, and triggers exactly when the regular
# CI workflows don't.

Expand All @@ -16,6 +16,7 @@ on:
branches:
- main
paths: # Trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md
# Or when a pull request event occurs for a pull request against one of the
Expand All @@ -24,6 +25,7 @@ on:
branches:
- main
paths: # Trigger if _only_ these files were changed.
- .punch_version.py
- .changelog/*.md
- CHANGELOG.md

Expand Down
17 changes: 17 additions & 0 deletions .punch_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Punch configuration file.

# For more information, see: https://punch.readthedocs.io/.

__config_version__ = 1

GLOBALS = {
'serializer': {
'semver': '{{ major }}.{{ minor }}.{{ patch }}',
}
}

# NOTE: The FILES list is not allowed to be empty, so we need to pass it at
# least a single valid file.
FILES = ["README.md"]

VERSION = ['major', 'minor', 'patch']
3 changes: 3 additions & 0 deletions .punch_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
major = 0
minor = 2
patch = 10
46 changes: 25 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -185,47 +185,51 @@ psql:
shutdown-postgres:
@docker rm nexus-postgres --force

confirm-version: fetch-git
@$(ECHO) "Latest published version is $(RED)v$(GIT_VERSION)$(OFF). You are about to publish $(CYAN)$(RELEASE_TAG)$(OFF)."
@$(ECHO) "If this is not what you want, re-run this command with RELEASE_VERSION=..."
@$(CONFIRM_ACTION)

# Fetch all the latest changes (including tags) from the canonical upstream git
# repository.
fetch-git:
@$(ECHO) "Fetching the latest changes (including tags) from $(GIT_ORIGIN_REMOTE) remote..."
@git fetch $(GIT_ORIGIN_REMOTE) --tags

# Used when RELEASE_VERSION is not set and until we have versioning tool in repo.
NEXT_PATCH_VERSION := $(shell echo $(GIT_VERSION) | awk 'BEGIN{FS=OFS="."} {$$NF = $$NF + 1; print}')
# Conditionally assign RELEASE_VERSION if it is not already set.
RELEASE_VERSION ?= $(NEXT_PATCH_VERSION)
# Git tag of the next release.
RELEASE_TAG := v$(RELEASE_VERSION)
# Private target for bumping project's version using the Punch tool.
# NOTE: It should not be invoked directly.
_version-bump: fetch-git
@$(ENSURE_VALID_RELEASE_BRANCH_NAME)
@$(PUNCH_BUMP_VERSION)
@git add $(PUNCH_VERSION_FILE)

# Private target for assembling the Change Log.
# NOTE: It should not be invoked directly.
_changelog:
@$(ECHO) "$(CYAN)*** Generating Change Log for version $(PUNCH_VERSION)...$(OFF)"
@$(BUILD_CHANGELOG)
@$(ECHO) "Next, review the staged changes, commit them and make a pull request."
@$(WARN_BREAKING_CHANGES)

# Assemble Change Log.
# NOTE: We need to call Make recursively since _version-bump target updates
# Punch's version and hence we need Make to re-evaluate the PUNCH_VERSION
# variable.
changelog: _version-bump
@$(MAKE) --no-print-directory _changelog

# Tag the next release.
release-tag: confirm-version
@$(ECHO) "Checking if we can tag version $(RELEASE_VERSION) as the next release..."
release-tag: fetch-git
@$(ECHO) "Checking if we can tag version $(PUNCH_VERSION) as the next release..."
@$(ENSURE_VALID_RELEASE_BRANCH_NAME)
@$(ENSURE_RELEASE_TAG_DOES_NOT_EXIST)
@$(ENSURE_NO_CHANGELOG_FRAGMENTS)
@$(ENSURE_NEXT_RELEASE_IN_CHANGELOG)
@$(ECHO) "All checks have passed. Proceeding with tagging the $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH)'s HEAD with tag '$(RELEASE_TAG)'."
@$(CONFIRM_ACTION)
@$(ECHO) "If this appears to be stuck, you might need to touch your security key for GPG sign operation."
@git tag --sign --message="Version $(RELEASE_VERSION)" $(RELEASE_TAG) $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH)
@git tag --sign --message="Version $(PUNCH_VERSION)" $(RELEASE_TAG) $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH)
@git push $(GIT_ORIGIN_REMOTE) $(RELEASE_TAG)
@$(ECHO) "$(CYAN)*** Tag '$(RELEASE_TAG)' has been successfully pushed to $(GIT_ORIGIN_REMOTE) remote.$(OFF)"

release-build: codegen-go
@goreleaser $(GORELEASER_ARGS)

changelog: confirm-version
@$(ECHO) "$(CYAN)*** Generating Change Log for version $(RELEASE_TAG)...$(OFF)"
@$(BUILD_CHANGELOG)
@$(ECHO) "Next, review the staged changes, commit them and make a pull request."
@$(WARN_BREAKING_CHANGES)

# List of targets that are not actual files.
.PHONY: \
all build \
Expand All @@ -239,7 +243,7 @@ changelog: confirm-version
clean \
test \
fmt \
changelog \
_version-bump _changelog changelog \
fetch-git \
release-tag \
$(lint-targets) lint \
Expand Down
76 changes: 70 additions & 6 deletions common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ GIT_VERSION := $(subst v,,$(shell \
echo undefined \
))

PUNCH_CONFIG_FILE := $(abspath $(SELF_DIR).punch_config.py)
PUNCH_VERSION_FILE := $(abspath $(SELF_DIR).punch_version.py)
# Obtain project's version as tracked by the Punch tool.
# NOTE: The Punch tool doesn't have the ability fo print project's version to
# stdout yet.
# For more details, see: https://github.com/lgiordani/punch/issues/42.
PUNCH_VERSION := $(shell \
python3 -c "exec(open('$(PUNCH_VERSION_FILE)').read()); \
print(f'{major}.{minor}.{patch}')" \
)

# Determine project's version.
# If the current git commit is exactly a tag and it equals the Punch version,
# then the project's version is that.
Expand All @@ -80,10 +91,48 @@ GO := env -u GOPATH $(OASIS_GO)
GOFLAGS ?= -trimpath -v

VERSION := $(or \
$(and $(call eq,$(GIT_COMMIT_EXACT_TAG),YES), $(GIT_VERSION)), \
$(shell git describe --tags --abbrev=0)-git$(shell git describe --always --match '' --dirty=+dirty 2>/dev/null) \
$(and $(call eq,$(GIT_COMMIT_EXACT_TAG),YES), $(call eq,$(GIT_VERSION),$(PUNCH_VERSION))), \
$(PUNCH_VERSION)-git$(shell git describe --always --match '' --dirty=+dirty 2>/dev/null) \
)

# Helper that bumps project's version with the Punch tool.
define PUNCH_BUMP_VERSION =
PART=patch; \
if [[ "$(RELEASE_BRANCH)" == main ]]; then \
if [[ -n "$(CHANGELOG_FRAGMENTS_BREAKING)" ]]; then \
PART=major; \
elif [[ -n "$(CHANGELOG_FRAGMENTS_FEATURES)" ]]; then \
PART=minor; \
fi; \
elif [[ "$(RELEASE_BRANCH)" == stable/* ]]; then \
if [[ -n "$(CHANGELOG_FRAGMENTS_BREAKING)" ]]; then \
$(ECHO) "$(RED)Error: There shouldn't be breaking changes in a release on a stable branch.$(OFF)"; \
$(ECHO) "List of detected breaking changes:"; \
for fragment in "$(CHANGELOG_FRAGMENTS_BREAKING)"; do \
$(ECHO) "- $$fragment"; \
done; \
exit 1; \
else \
PART=patch; \
fi; \
else \
$(ECHO) "$(RED)Error: Unsupported release branch: '$(RELEASE_BRANCH)'.$(OFF)"; \
exit 1; \
fi; \
punch --config-file $(PUNCH_CONFIG_FILE) --version-file $(PUNCH_VERSION_FILE) --part $$PART --quiet
endef

# Helper that ensures project's version determined from git equals project's
# version as tracked by the Punch tool.
define ENSURE_GIT_VERSION_EQUALS_PUNCH_VERSION =
if [[ "$(GIT_VERSION)" != "$(PUNCH_VERSION)" ]]; then \
$(ECHO) "$(RED)Error: Project's version for $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH) \
determined from git ($(GIT_VERSION)) doesn't equal project's version in \
$(PUNCH_VERSION_FILE) ($(PUNCH_VERSION)).$(OFF)"; \
exit 1; \
fi
endef

# Project's version as the linker's string value definition.
export GOLDFLAGS_VERSION := -X github.com/oasisprotocol/nexus/version.Software=$(VERSION)

Expand Down Expand Up @@ -124,6 +173,9 @@ endef
# List of non-trivial Change Log fragments.
CHANGELOG_FRAGMENTS_NON_TRIVIAL := $(filter-out $(wildcard .changelog/*trivial*.md),$(wildcard .changelog/[0-9]*.md))

# List of minor Change Log fragments.
CHANGELOG_FRAGMENTS_FEATURES := $(wildcard .changelog/*feature*.md)

# List of breaking Change Log fragments.
CHANGELOG_FRAGMENTS_BREAKING := $(wildcard .changelog/*breaking*.md)

Expand All @@ -140,9 +192,9 @@ endef
# Helper that builds the Change Log.
define BUILD_CHANGELOG =
if [[ $(ASSUME_YES) != 1 ]]; then \
towncrier build --version $(RELEASE_VERSION); \
towncrier build --version $(PUNCH_VERSION); \
else \
towncrier build --version $(RELEASE_VERSION) --yes; \
towncrier build --version $(PUNCH_VERSION) --yes; \
fi
endef

Expand Down Expand Up @@ -173,8 +225,20 @@ endef
# section for the next release.
define ENSURE_NEXT_RELEASE_IN_CHANGELOG =
if ! ( git show $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH):CHANGELOG.md | \
grep --quiet '^## $(RELEASE_VERSION) (.*)' ); then \
$(ECHO) "$(RED)Error: Could not locate Change Log section for release $(RELEASE_VERSION) on $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH) branch.$(OFF)"; \
grep --quiet '^## $(PUNCH_VERSION) (.*)' ); then \
$(ECHO) "$(RED)Error: Could not locate Change Log section for release $(PUNCH_VERSION) on $(GIT_ORIGIN_REMOTE)/$(RELEASE_BRANCH) branch.$(OFF)"; \
exit 1; \
fi
endef

# Git tag of the next release.
RELEASE_TAG := v$(PUNCH_VERSION)

# Helper that ensures the new release's tag doesn't already exist on the origin
# remote.
define ENSURE_RELEASE_TAG_EXISTS =
if ! git ls-remote --exit-code --tags $(GIT_ORIGIN_REMOTE) $(RELEASE_TAG) 1>/dev/null; then \
$(ECHO) "$(RED)Error: Tag '$(RELEASE_TAG)' doesn't exist on $(GIT_ORIGIN_REMOTE) remote.$(OFF)"; \
exit 1; \
fi
endef
Expand Down

0 comments on commit 4f00f86

Please sign in to comment.