From 1d0ec49b5669f30d568a621cf2db3049f3f83229 Mon Sep 17 00:00:00 2001 From: OzBena <109233461+OzBena@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:55:11 +0300 Subject: [PATCH] Refactor/version migrate to file based versioning (#6) * Added version.txt and corresponding handler. And fixed relative path issue caused by the change * Added workflow for static version model. * Fixed version handling in the Makefile. * versioning and tagging workflow docs added --- .github/workflows/tag-version.yml | 29 ++++++++++++++++ .goreleaser.yml | 2 +- CONTRIBUTING.md | 56 ++++++++++++++++++++++++++++--- cmd/version.go | 5 ++- makefile | 6 +++- pkg/utils/file_test.go | 3 +- teamcity/queue.go | 3 +- version/handler.go | 27 +++++++++++++++ version/version.go | 27 --------------- version/version.txt | 1 + 10 files changed, 119 insertions(+), 40 deletions(-) create mode 100644 .github/workflows/tag-version.yml create mode 100644 version/handler.go delete mode 100644 version/version.go create mode 100644 version/version.txt diff --git a/.github/workflows/tag-version.yml b/.github/workflows/tag-version.yml new file mode 100644 index 0000000..3f5462a --- /dev/null +++ b/.github/workflows/tag-version.yml @@ -0,0 +1,29 @@ +name: Tag on Version Change + +on: + push: + branches: + - master + paths: + - "version/version.txt" + +jobs: + create_tag: + runs-on: ubuntu-latest + + steps: + - name: Checkout the code + uses: actions/checkout@v4 + + - name: Read version from version.txt + id: read_version + run: | + VERSION=$(cat version/version.txt) + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Create and push tag + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "v${{ env.VERSION }}" -m "Release version ${{ env.VERSION }}" + git push origin "v${{ env.VERSION }}" diff --git a/.goreleaser.yml b/.goreleaser.yml index e2a725f..6338ddc 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,7 +10,7 @@ builds: - amd64 - arm64 ldflags: - - -s -w -X bbox/version.version={{.Version}} -X bbox/version.commit={{.Commit}} -X bbox/version.date={{.Date}} -X bbox/version.builtBy=goreleaser + - -s -w archives: - format: tar.gz diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5141e1f..24cf095 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,10 +9,11 @@ Thank you for your interest in contributing to BBOX! We appreciate your efforts 3. [How to Suggest Documentation Improvements](#how-to-suggest-documentation-improvements) 4. [How to Submit a Pull Request](#how-to-submit-a-pull-request) 5. [Branch Naming Convention](#branch-naming-convention) -6. [Style Guide](#style-guide) -7. [Testing](#testing) -8. [Documentation](#documentation) -9. [Communication](#communication) +6. [Versioning and Tagging Workflow](#versioning-and-tagging-workflow) +7. [Style Guide](#style-guide) +8. [Testing](#testing) +9. [Documentation](#documentation) +10. [Communication](#communication) ## How to Report a Bug @@ -71,6 +72,53 @@ For example: feat/clean_add-new-clean-feature ``` +## Versioning and Tagging Workflow + +BBOX uses a versioning and tagging system to manage releases, following semantic versioning principles. Here’s how the process works: + +### Semantic Versioning + +The version number in `version/version.txt` follows semantic versioning: + +- **MAJOR** version (`v1.0.0`) is incremented when you make incompatible API changes. +- **MINOR** version (`v1.1.0`) is incremented when you add functionality in a backward-compatible manner. +- **PATCH** version (`v1.1.1`) is incremented when you make backward-compatible bug fixes. +- Additional labels for pre-release and build metadata (e.g., `v1.1.0-rc1`) are available as extensions to the MAJOR.MINOR.PATCH format. + +### Versioning Workflow + +1. **Updating the Version**: + - Before submitting a Pull Request (PR), update the `version.txt` file with the new version number based on the changes you are introducing (e.g., `v1.1.0` or `v1.1.0-rc1` for release candidates). + +2. **Committing the Version Change**: + - Commit the change to `version.txt` with a descriptive commit message following our convention. + - For example: `release/version_Update-to-v1.1.0`. + +3. **Submit a Pull Request**: + - Once the version update is ready, submit your PR for review. The version change will only take effect after the PR is approved and merged into the `master` branch. + +4. **Automatic Tagging**: + - When the change to `version.txt` is merged into the `master` branch, a GitHub Actions workflow automatically creates a new Git tag based on the version number in `version.txt`. + - The tag will follow the format: + - `v*.*.*` for regular releases (e.g., `v1.1.0`). + - `v*.*.*-rc*` for release candidates (e.g., `v1.1.0-rc1`). + +5. **Release Process**: + - The creation of the tag will trigger a separate GitHub Actions workflow that runs GoReleaser to build and publish the release. + - This process will include: + - **Building and publishing binaries**. + - **Creating a new Docker image and pushing it to DockerHub**. + +### Example Workflow: + +1. Update `version.txt` with the new version number (e.g., `v1.1.0` or `v1.1.0-rc1`). +2. Commit the change: `git commit -m "chore/version_Update-to-v1.1.0"`. +3. Submit a PR for review. +4. After the PR is approved and merged into `master`, the tagging workflow will automatically create a new tag (e.g., `v1.1.0`). +5. The release workflow will then: + - Build and publish the new version using GoReleaser. + - Create and push a new Docker image to DockerHub. + ## Style Guide Please adhere to the following coding standards: diff --git a/cmd/version.go b/cmd/version.go index 1d0e08e..57f1531 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -4,9 +4,8 @@ Copyright © 2024 NAME HERE package cmd import ( - "fmt" - "bbox/version" + "fmt" "github.com/spf13/cobra" ) @@ -20,6 +19,6 @@ var versionCmd = &cobra.Command{ Use: "version", Short: "Print the version number of bbox", Run: func(cmd *cobra.Command, args []string) { - fmt.Println("bbox version:", version.GetFormattedVersion()) + fmt.Println("bbox version:", version.GetVersion()) }, } diff --git a/makefile b/makefile index a68bf6d..a5a516d 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,8 @@ +.PHONY: test lint help version + NAME ?= bbox GOCMD=go GOTEST=$(GOCMD) test -VERSION := $(shell $(GOCMD) run main.go) test: ## Run tests for the project $(GOTEST) ./... -v @@ -12,3 +13,6 @@ lint: ## Run linter help: ## Show Help menu @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' +version: ## Show bbox current version + $(GOCMD) run bbox version + diff --git a/pkg/utils/file_test.go b/pkg/utils/file_test.go index d6b0098..efba69d 100644 --- a/pkg/utils/file_test.go +++ b/pkg/utils/file_test.go @@ -1,7 +1,6 @@ package utils_test import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -16,7 +15,7 @@ func TestUnzipFile(t *testing.T) { destDir := "/tmp" // Create a temporary directory for testing - tempDir, err := ioutil.TempDir("", "unzip_test") + tempDir, err := os.MkdirTemp("", "unzip_test") assert.NoError(t, err) defer os.RemoveAll(tempDir) diff --git a/teamcity/queue.go b/teamcity/queue.go index 92d805f..204a190 100644 --- a/teamcity/queue.go +++ b/teamcity/queue.go @@ -3,7 +3,6 @@ package teamcity import ( "fmt" "io" - "io/ioutil" "net/http" log "github.com/sirupsen/logrus" @@ -31,7 +30,7 @@ func (qs *QueueService) ClearQueue() error { // Check the response. Expecting HTTP Status No Content (204) or OK (200) as a success indicator. if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusNoContent { - bodyBytes, _ := ioutil.ReadAll(response.Body) + bodyBytes, _ := io.ReadAll(response.Body) return fmt.Errorf("failed to clear the queue, status code: %d, response: %s", response.StatusCode, string(bodyBytes)) } diff --git a/version/handler.go b/version/handler.go new file mode 100644 index 0000000..debe818 --- /dev/null +++ b/version/handler.go @@ -0,0 +1,27 @@ +package version + +import ( + "embed" + "log" + "strings" +) + +var ( + // Version is loaded from version.txt file + version = loadVersionFromFile() + + //go:embed version.txt + embedFS embed.FS +) + +func GetVersion() string { + return version +} + +func loadVersionFromFile() string { + data, err := embedFS.ReadFile("version.txt") + if err != nil { + log.Fatalf("Failed to read version file: %v", err) + } + return strings.TrimSpace(string(data)) +} diff --git a/version/version.go b/version/version.go deleted file mode 100644 index 84d37b6..0000000 --- a/version/version.go +++ /dev/null @@ -1,27 +0,0 @@ -package version - -import "fmt" - -// Set with LDFLAGS. -var ( - // Version of the release, the value will be injected by .goreleaser - version = `` - - // Commit hash of the release, the value will be injected by .goreleaser - commit = ` development` - - // Commit date of the release, the value will be injected by .goreleaser - date = `` - - // BuiltBy of the release, the value will be injected by .goreleaser - builtBy = `hasn't been built yet` -) - -func GetVersion() string { - return version -} - -// GetFormattedVersion returns the current version and commit hash -func GetFormattedVersion() string { - return fmt.Sprintf("%s (%s %s)\nbuilt by: %s", version, commit, date, builtBy) -} diff --git a/version/version.txt b/version/version.txt new file mode 100644 index 0000000..8b8013f --- /dev/null +++ b/version/version.txt @@ -0,0 +1 @@ +v1.0.0-rc \ No newline at end of file