mirror of
https://github.com/lukaszraczylo/semver-generator.git
synced 2026-06-20 01:51:22 +00:00
Compare commits
2 Commits
v1
...
update-march-2025
| Author | SHA1 | Date | |
|---|---|---|---|
| 98f6c31e9d | |||
| f87a53ec65 |
@@ -1,69 +1,137 @@
|
|||||||
## Semantic version generator
|
# Semantic Version Generator
|
||||||
|
|
||||||
[](https://github.com/lukaszraczylo/semver-generator/actions/workflows/release.yaml)  [](https://codecov.io/gh/lukaszraczylo/semver-generator)
|
[](https://github.com/lukaszraczylo/semver-generator/actions/workflows/release.yaml)  [](https://codecov.io/gh/lukaszraczylo/semver-generator)
|
||||||
|
|
||||||
Project created overnight, to prove that management of semantic versioning is NOT painful and do not require arguments and debates within the team. Simple, clean and only thing the project team should need to agree to are the keywords.
|
A lightweight, configurable tool that simplifies semantic versioning by automatically calculating version numbers based on git commit messages. No more manual version management or team debates about versioning - just agree on the keywords and let the tool handle the rest.
|
||||||
|
|
||||||
- [Semantic version generator](#semantic-version-generator)
|
## Table of Contents
|
||||||
- [How does it work](#how-does-it-work)
|
|
||||||
- [Additional features](#additional-features)
|
|
||||||
- [Important changes](#important-changes)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Authentication](#authentication)
|
|
||||||
- [As a binary](#as-a-binary)
|
|
||||||
- [As a github action](#as-a-github-action)
|
|
||||||
- [As a docker container](#as-a-docker-container)
|
|
||||||
- [Calculations example \[standard\]](#calculations-example-standard)
|
|
||||||
- [Calculations example \[strict matching\]](#calculations-example-strict-matching)
|
|
||||||
- [Release candidates](#release-candidates)
|
|
||||||
- [Example configuration](#example-configuration)
|
|
||||||
- [Good to know](#good-to-know)
|
|
||||||
|
|
||||||
### How does it work
|
- [How It Works](#how-it-works)
|
||||||
|
- [Key Features](#key-features)
|
||||||
|
- [Important Changes](#important-changes)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Prerequisites](#prerequisites)
|
||||||
|
- [Binary](#binary)
|
||||||
|
- [Docker](#docker)
|
||||||
|
- [GitHub Action](#github-action)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [Authentication](#authentication)
|
||||||
|
- [Command Line Options](#command-line-options)
|
||||||
|
- [Configuration File](#configuration-file)
|
||||||
|
- [Versioning Behavior](#versioning-behavior)
|
||||||
|
- [Release Candidates](#release-candidates)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Standard Mode](#standard-mode)
|
||||||
|
- [Strict Matching Mode](#strict-matching-mode)
|
||||||
|
- [Advanced Features](#advanced-features)
|
||||||
|
- [Force Settings](#force-settings)
|
||||||
|
- [Blacklist Terms](#blacklist-terms)
|
||||||
|
- [Tips & Best Practices](#tips--best-practices)
|
||||||
|
|
||||||
* Binary clones the github repository
|
## How It Works
|
||||||
* Iterates through the list of commits looking for the keywords specified in config file for additional bumps of versions
|
|
||||||
* Returns the semantic version which can be included in the release
|
|
||||||
|
|
||||||
### Additional features
|
The semantic version generator follows a simple process:
|
||||||
|
|
||||||
* With flag `-e` or config `force.existing: true` the existing tags in versioning will be respected, helping you to avoid the version conflicts.
|
1. Clones the specified GitHub repository (or uses a local repository)
|
||||||
* With config `force.commit: deadbeef` where `deadbeef` is the commit hash - calculations will start from the specified commit.
|
2. Iterates through the commit history, analyzing each commit message
|
||||||
|
3. Looks for predefined keywords (configurable) that trigger version increments
|
||||||
|
4. Calculates the appropriate semantic version based on the matches
|
||||||
|
5. Returns the resulting version that can be used for releases
|
||||||
|
|
||||||
### Important changes
|
## Key Features
|
||||||
|
|
||||||
* From version `1.4.2+` as pointed out in [issue #12](https://github.com/lukaszraczylo/semver-generator/issues/12) commits from merge will not be included in the calculations and commits themselves will bump the version on first match ( starting checks from `patch` upwards ).
|
- **Effortless Version Calculation**: Automatically determine the appropriate version based on commit messages
|
||||||
* Added support for blacklisting terms to ignore specific commits, branch names, and merge messages from version calculations.
|
- **Configurable Keywords**: Define your own keywords for patch, minor, and major version increments
|
||||||
|
- **Support for Existing Tags**: Option to respect existing version tags to avoid conflicts
|
||||||
|
- **Release Candidate Support**: Generate release candidate versions with incrementing counter (e.g., `1.2.3-rc.1`)
|
||||||
|
- **Flexible Repository Source**: Work with either local or remote Git repositories
|
||||||
|
- **Blacklist Support**: Ignore specific commits or branch merges from version calculations
|
||||||
|
- **Force Options**: Start calculations from a specific commit or set a minimum version
|
||||||
|
|
||||||
### Usage
|
## Important Changes
|
||||||
|
|
||||||
#### Authentication
|
- **Since v1.4.2+**: Commits from merge requests are no longer included in calculations
|
||||||
|
- **Commit Matching Behavior**: Commits will bump the version on the first match (checking from `patch` upwards)
|
||||||
|
- **Blacklist Support**: Added ability to ignore specific terms in commit messages, branch names, and merge requests
|
||||||
|
|
||||||
If you intend to use this project with remote repositories ( regardless of them being private or public ) you need to authenticate with your repository.
|
## Installation
|
||||||
To do so you can utilise the following environment variables ( they are NOT github specific, for other providers you can use the password )
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
When using with remote repositories, authentication is required. Set the following environment variables:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export GITHUB_USERNAME=lukaszraczylo
|
export GITHUB_USERNAME=yourusername
|
||||||
export GITHUB_TOKEN=yourPersonalApiToken
|
export GITHUB_TOKEN=yourpersonalapitoken
|
||||||
```
|
```
|
||||||
|
|
||||||
#### As a binary
|
### Binary
|
||||||
|
|
||||||
You can download latest versions of the binaries from the [release page](https://github.com/lukaszraczylo/semver-generator/releases/latest).
|
Download the latest binary from the [release page](https://github.com/lukaszraczylo/semver-generator/releases/latest).
|
||||||
|
|
||||||
**Supported OS and architectures:**
|
**Supported platforms**:
|
||||||
Darwin ARM64/AMD64, Linux ARM64/AMD64, Windows AMD64
|
- Darwin (macOS): ARM64/AMD64
|
||||||
|
- Linux: ARM64/AMD64
|
||||||
|
- Windows: AMD64
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash$ ./semver-gen generate -r https://github.com/nextapps-de/winbox
|
docker pull ghcr.io/lukaszraczylo/semver-generator:latest
|
||||||
SEMVER 9.0.10
|
|
||||||
bash$ ./semver-gen generate -l
|
|
||||||
SEMVER 5.1.1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Local repository flag `-l` will always take precedence over remote repository URL**
|
**Supported architectures**:
|
||||||
|
- Linux/arm64
|
||||||
|
- Linux/amd64
|
||||||
|
|
||||||
|
### GitHub Action
|
||||||
|
|
||||||
|
Add to your GitHub workflow:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
jobs:
|
||||||
|
prepare:
|
||||||
|
name: Preparing build context
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
RELEASE_VERSION: ${{ steps.semver.outputs.semantic_version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: '0'
|
||||||
|
- name: Semver run
|
||||||
|
id: semver
|
||||||
|
uses: lukaszraczylo/semver-generator@v1
|
||||||
|
with:
|
||||||
|
config_file: semver.yaml
|
||||||
|
# Either use local repository
|
||||||
|
repository_local: true
|
||||||
|
# Or specify remote repository
|
||||||
|
# repository_url: https://github.com/lukaszraczylo/simple-gql-client
|
||||||
|
# github_username: ${{ secrets.GH_USERNAME }}
|
||||||
|
# github_token: ${{ secrets.GH_TOKEN }}
|
||||||
|
strict: false
|
||||||
|
existing: true
|
||||||
|
- name: Use semantic version
|
||||||
|
run: |
|
||||||
|
echo "Semantic version detected: ${{ steps.semver.outputs.semantic_version }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
For remote repositories (public or private), authenticate using:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export GITHUB_USERNAME=yourusername
|
||||||
|
export GITHUB_TOKEN=yourpersonalapitoken
|
||||||
|
```
|
||||||
|
|
||||||
|
### Command Line Options
|
||||||
|
|
||||||
|
```
|
||||||
Usage:
|
Usage:
|
||||||
semver-gen generate [flags]
|
semver-gen generate [flags]
|
||||||
semver-gen [command]
|
semver-gen [command]
|
||||||
@@ -85,86 +153,11 @@ Flags:
|
|||||||
-v, --version Display version
|
-v, --version Display version
|
||||||
```
|
```
|
||||||
|
|
||||||
#### As a github action
|
**Note**: The `-l/--local` flag takes precedence over the repository URL.
|
||||||
|
|
||||||
```yaml
|
### Configuration File
|
||||||
jobs:
|
|
||||||
prepare:
|
|
||||||
name: Preparing build context
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
RELEASE_VERSION: ${{ steps.semver.outputs.semantic_version }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repo
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: '0'
|
|
||||||
- name: Semver run
|
|
||||||
id: semver
|
|
||||||
uses: lukaszraczylo/semver-generator@PLACE_LATEST_TAG_HERE
|
|
||||||
# you can also use v1 tag which _should_ automatically upgrade to latest
|
|
||||||
# uses: lukaszraczylo/semver-generator@v1
|
|
||||||
with:
|
|
||||||
config_file: semver.yaml
|
|
||||||
# either...
|
|
||||||
repository_local: true
|
|
||||||
# or...
|
|
||||||
repository_url: https://github.com/lukaszraczylo/simple-gql-client
|
|
||||||
# when using remote repository, especially with private one:
|
|
||||||
github_username: lukaszraczylo
|
|
||||||
github_token: MySupeRSecr3tPa$$w0rd
|
|
||||||
strict: true
|
|
||||||
existing: false
|
|
||||||
- name: Semver check
|
|
||||||
run: |
|
|
||||||
echo "Semantic version detected: ${{ steps.semver.outputs.semantic_version }}"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### As a docker container
|
Create a `semver.yaml` file (or specify a different path with `-c`):
|
||||||
|
|
||||||
```bash
|
|
||||||
docker pull ghcr.io/lukaszraczylo/semver-generator:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
**Docker supported architectures:**
|
|
||||||
Linux/arm64, Linux/amd64
|
|
||||||
|
|
||||||
#### Calculations example [standard]
|
|
||||||
|
|
||||||
```bash
|
|
||||||
- 0.0.1 - PATCH - starting commit
|
|
||||||
- 0.0.2 - PATCH - another commit
|
|
||||||
- 0.0.4 - PATCH - another commit with word 'Update' => DOUBLE increment PATCH
|
|
||||||
- 0.1.0 - MINOR - after commit with word 'Change' => increment MINOR, reset PATCH
|
|
||||||
- 0.1.1 - PATCH - additional commit
|
|
||||||
- 1.0.1 - MAJOR - commit with word 'BREAKING' = > INCREMENT MAJOR, reset MINOR
|
|
||||||
- 1.0.2 - PATCH - another commit
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Calculations example [strict matching]
|
|
||||||
|
|
||||||
```bash
|
|
||||||
- 0.0.1 - PATCH - starting commit
|
|
||||||
- 0.0.1 - PATCH - another commit
|
|
||||||
- 0.0.1 - PATCH - another commit with word 'Update' => SINGLE increment PATCH
|
|
||||||
- 0.1.0 - MINOR - after commit with word 'Change' => increment MINOR, reset PATCH
|
|
||||||
- 0.1.0 - PATCH - additional commit
|
|
||||||
- 1.0.0 - MAJOR - commit with word 'BREAKING' = > INCREMENT MAJOR, reset MINOR
|
|
||||||
- 1.0.0 - PATCH - another commit
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Release candidates
|
|
||||||
|
|
||||||
The `semver-gen` supports release candidates generation as well. Add following configuration ( and change the trigger keywords to anything what suits you )
|
|
||||||
to generate the appropriate release in format `1.3.37-rc.1` and counting up until next `minor` trigger will be detected.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
release:
|
|
||||||
- release-candidate
|
|
||||||
- add-rc
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Example configuration
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: 1
|
version: 1
|
||||||
@@ -173,6 +166,8 @@ force:
|
|||||||
minor: 0
|
minor: 0
|
||||||
patch: 1
|
patch: 1
|
||||||
commit: 69fbe2df696f40281b9104ff073d26186cde1024
|
commit: 69fbe2df696f40281b9104ff073d26186cde1024
|
||||||
|
existing: true
|
||||||
|
strict: false
|
||||||
blacklist:
|
blacklist:
|
||||||
- "Merge branch"
|
- "Merge branch"
|
||||||
- "Merge pull request"
|
- "Merge pull request"
|
||||||
@@ -182,25 +177,111 @@ wording:
|
|||||||
patch:
|
patch:
|
||||||
- update
|
- update
|
||||||
- initial
|
- initial
|
||||||
|
- fix
|
||||||
minor:
|
minor:
|
||||||
- change
|
- change
|
||||||
- improve
|
- improve
|
||||||
|
- add
|
||||||
major:
|
major:
|
||||||
- breaking
|
- breaking
|
||||||
- the # For testing purposes
|
- redesign
|
||||||
release:
|
release:
|
||||||
- release-candidate
|
- release-candidate
|
||||||
- add-rc
|
- add-rc
|
||||||
```
|
```
|
||||||
|
|
||||||
* `version`: is not respected at the moment, introduced for potential backwards compatibility in future
|
Configuration options:
|
||||||
* `force`: sets the "starting" version, you don't need to specify this section as the default is always `0`
|
- `version`: Reserved for future backward compatibility
|
||||||
* `force.commit`: allows you to set commit hash from which the calculations should start
|
- `force`: Set starting version or other constraints
|
||||||
* `blacklist`: terms to ignore when processing commits. Any commit containing these terms will be skipped in version calculations. Useful for ignoring merge commits, feature branch names, and other unwanted triggers.
|
- `blacklist`: Terms to ignore when processing commits
|
||||||
* `wording`: words the program should look for in the git commits to increment (patch|minor|major)
|
- `wording`: Keywords that trigger version increments
|
||||||
|
|
||||||
### Good to know
|
### Versioning Behavior
|
||||||
|
|
||||||
* Word matching uses fuzzy search AND is case INSENSITIVE
|
The version calculation follows semantic versioning rules:
|
||||||
* I do not recommend using common words ( like "the" from the example configuration )
|
- **MAJOR**: Incremented for incompatible API changes
|
||||||
* You can specify env variable `LOG_LEVEL=debug` to see what exactly happens during the calculations
|
- **MINOR**: Incremented for backward-compatible new features
|
||||||
|
- **PATCH**: Incremented for backward-compatible bug fixes
|
||||||
|
|
||||||
|
When keywords are matched:
|
||||||
|
- **MAJOR** match: Increments major version, resets minor and patch versions
|
||||||
|
- **MINOR** match: Increments minor version, resets patch version
|
||||||
|
- **PATCH** match: Increments patch version
|
||||||
|
- By default (non-strict mode), every commit increments patch version
|
||||||
|
|
||||||
|
### Release Candidates
|
||||||
|
|
||||||
|
Add the following to your configuration to generate release candidates:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
wording:
|
||||||
|
release:
|
||||||
|
- release-candidate
|
||||||
|
- add-rc
|
||||||
|
```
|
||||||
|
|
||||||
|
When a release candidate keyword is found, the version will be formatted as `1.2.3-rc.1`, with the counter incrementing for each new release candidate.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Standard Mode
|
||||||
|
|
||||||
|
```
|
||||||
|
- 0.0.1 - PATCH - starting commit
|
||||||
|
- 0.0.2 - PATCH - another commit
|
||||||
|
- 0.0.4 - PATCH - another commit with word 'Update' => DOUBLE increment PATCH
|
||||||
|
- 0.1.0 - MINOR - after commit with word 'Change' => increment MINOR, reset PATCH
|
||||||
|
- 0.1.1 - PATCH - additional commit
|
||||||
|
- 1.0.1 - MAJOR - commit with word 'BREAKING' => INCREMENT MAJOR, reset MINOR
|
||||||
|
- 1.0.2 - PATCH - another commit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Strict Matching Mode
|
||||||
|
|
||||||
|
In strict mode (using `-s` flag or `force.strict: true`), versions only increment when a keyword is matched:
|
||||||
|
|
||||||
|
```
|
||||||
|
- 0.0.1 - PATCH - starting commit
|
||||||
|
- 0.0.1 - PATCH - another commit (no change - no keyword match)
|
||||||
|
- 0.0.2 - PATCH - another commit with word 'Update' => increment PATCH
|
||||||
|
- 0.1.0 - MINOR - after commit with word 'Change' => increment MINOR, reset PATCH
|
||||||
|
- 0.1.0 - PATCH - additional commit (no change - no keyword match)
|
||||||
|
- 1.0.0 - MAJOR - commit with word 'BREAKING' => INCREMENT MAJOR, reset MINOR
|
||||||
|
- 1.0.0 - PATCH - another commit (no change - no keyword match)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Features
|
||||||
|
|
||||||
|
### Force Settings
|
||||||
|
|
||||||
|
Control versioning with force settings in configuration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
force:
|
||||||
|
major: 1 # Set minimum major version
|
||||||
|
minor: 0 # Set minimum minor version
|
||||||
|
patch: 1 # Set minimum patch version
|
||||||
|
commit: 69fbe2df696f40281b9104ff073d26186cde1024 # Start from specific commit
|
||||||
|
existing: true # Respect existing tags (same as -e flag)
|
||||||
|
strict: false # Use strict matching (same as -s flag)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Blacklist Terms
|
||||||
|
|
||||||
|
Ignore specific commits from version calculations:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
blacklist:
|
||||||
|
- "Merge branch" # Ignore merge commits
|
||||||
|
- "Merge pull request" # Ignore PR merges
|
||||||
|
- "feature/" # Ignore feature branch names
|
||||||
|
- "chore:" # Ignore chore commits
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips & Best Practices
|
||||||
|
|
||||||
|
- Word matching uses fuzzy search and is case INSENSITIVE
|
||||||
|
- Avoid common words as version triggers (e.g., "the", "and")
|
||||||
|
- Use `LOG_LEVEL=debug` environment variable to see detailed calculation steps
|
||||||
|
- When using as a GitHub Action, ensure `fetch-depth: '0'` to get the complete commit history
|
||||||
|
- For complex projects, consider using a more specific configuration to distinguish between types of changes
|
||||||
|
|||||||
+12
-13
@@ -26,27 +26,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
|
||||||
repo *Setup
|
repo *Setup
|
||||||
PKG_VERSION string
|
PKG_VERSION string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup represents the application setup
|
// Setup represents the application setup
|
||||||
type Setup struct {
|
type Setup struct {
|
||||||
RepositoryName string
|
RepositoryName string
|
||||||
RepositoryBranch string
|
RepositoryBranch string
|
||||||
LocalConfigFile string
|
LocalConfigFile string
|
||||||
Generate bool
|
Generate bool
|
||||||
UseLocal bool
|
UseLocal bool
|
||||||
GitRepo utils.GitRepository
|
GitRepo utils.GitRepository
|
||||||
Config *utils.Config
|
Config *utils.Config
|
||||||
Semver utils.SemVer
|
Semver utils.SemVer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the fuzzy search function in the utils package
|
// Initialize the fuzzy search function in the utils package
|
||||||
func init() {
|
func init() {
|
||||||
utils.InitLogger(false) // Will be updated in main based on debug flag
|
utils.InitLogger(false) // Will be updated in main based on debug flag
|
||||||
|
|
||||||
// Set the fuzzy search function
|
// Set the fuzzy search function
|
||||||
utils.FuzzyFind = fuzzy.FindNormalizedFold
|
utils.FuzzyFind = fuzzy.FindNormalizedFold
|
||||||
}
|
}
|
||||||
@@ -72,12 +71,12 @@ func main() {
|
|||||||
if PKG_VERSION != latestRelease && latestReleaseOk {
|
if PKG_VERSION != latestRelease && latestReleaseOk {
|
||||||
outdatedMsg = fmt.Sprintf("(Latest available: %s)", latestRelease)
|
outdatedMsg = fmt.Sprintf("(Latest available: %s)", latestRelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.Info("semver-gen", map[string]interface{}{
|
utils.Info("semver-gen", map[string]interface{}{
|
||||||
"version": PKG_VERSION,
|
"version": PKG_VERSION,
|
||||||
"outdated": outdatedMsg,
|
"outdated": outdatedMsg,
|
||||||
})
|
})
|
||||||
|
|
||||||
if outdatedMsg != "" {
|
if outdatedMsg != "" {
|
||||||
utils.Info("semver-gen", map[string]interface{}{
|
utils.Info("semver-gen", map[string]interface{}{
|
||||||
"message": "You can update automatically with: semver-gen -u",
|
"message": "You can update automatically with: semver-gen -u",
|
||||||
|
|||||||
+10
-10
@@ -267,7 +267,7 @@ func (suite *Tests) Test_checkMatches() {
|
|||||||
if tt.name == "No match" {
|
if tt.name == "No match" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// For other test cases, match if the needle is in the haystack
|
// For other test cases, match if the needle is in the haystack
|
||||||
for _, h := range haystack {
|
for _, h := range haystack {
|
||||||
if strings.Contains(h, needle) || strings.Contains(needle, h) {
|
if strings.Contains(h, needle) || strings.Contains(needle, h) {
|
||||||
@@ -276,7 +276,7 @@ func (suite *Tests) Test_checkMatches() {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
got := utils.CheckMatches(tt.args.content, tt.args.targets, tt.blacklist)
|
got := utils.CheckMatches(tt.args.content, tt.args.targets, tt.blacklist)
|
||||||
assertObj.Equal(tt.want, got, "Unexpected result in "+tt.name)
|
assertObj.Equal(tt.want, got, "Unexpected result in "+tt.name)
|
||||||
})
|
})
|
||||||
@@ -382,10 +382,10 @@ func (suite *Tests) Test_parseExistingSemver() {
|
|||||||
|
|
||||||
func (suite *Tests) TestSetup_ListCommits() {
|
func (suite *Tests) TestSetup_ListCommits() {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
RepositoryName string
|
RepositoryName string
|
||||||
RepositoryBranch string
|
RepositoryBranch string
|
||||||
LocalConfigFile string
|
LocalConfigFile string
|
||||||
GitRepo utils.GitRepository
|
GitRepo utils.GitRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@@ -441,23 +441,23 @@ func (suite *Tests) TestSetup_ListCommits() {
|
|||||||
if tt.name == "List commits from existing repository" {
|
if tt.name == "List commits from existing repository" {
|
||||||
t.Skip("Skipping test that requires repository access")
|
t.Skip("Skipping test that requires repository access")
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Setup{
|
s := &Setup{
|
||||||
RepositoryName: tt.fields.RepositoryName,
|
RepositoryName: tt.fields.RepositoryName,
|
||||||
RepositoryBranch: tt.fields.RepositoryBranch,
|
RepositoryBranch: tt.fields.RepositoryBranch,
|
||||||
GitRepo: tt.fields.GitRepo,
|
GitRepo: tt.fields.GitRepo,
|
||||||
}
|
}
|
||||||
|
|
||||||
config, _ := utils.ReadConfig(tt.fields.LocalConfigFile)
|
config, _ := utils.ReadConfig(tt.fields.LocalConfigFile)
|
||||||
s.Config = config
|
s.Config = config
|
||||||
|
|
||||||
err := utils.PrepareRepository(&s.GitRepo)
|
err := utils.PrepareRepository(&s.GitRepo)
|
||||||
if err != nil && !tt.wantErr {
|
if err != nil && !tt.wantErr {
|
||||||
if tt.name != "List commits starting with certain hash" {
|
if tt.name != "List commits starting with certain hash" {
|
||||||
t.Fatalf("Failed to prepare repository: %v", err)
|
t.Fatalf("Failed to prepare repository: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
listOfCommits, err := utils.ListCommits(&s.GitRepo)
|
listOfCommits, err := utils.ListCommits(&s.GitRepo)
|
||||||
if !tt.wantErr {
|
if !tt.wantErr {
|
||||||
|
|||||||
+3
-3
@@ -30,13 +30,13 @@ func TestExecute(t *testing.T) {
|
|||||||
Short: "Test command",
|
Short: "Test command",
|
||||||
Run: func(cmd *cobra.Command, args []string) {},
|
Run: func(cmd *cobra.Command, args []string) {},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the required flags to the test command
|
// Add all the required flags to the test command
|
||||||
testCmd.Flags().Bool("version", false, "Print version information")
|
testCmd.Flags().Bool("version", false, "Print version information")
|
||||||
testCmd.Flags().String("repository", "test-repo", "Repository URL")
|
testCmd.Flags().String("repository", "test-repo", "Repository URL")
|
||||||
testCmd.Flags().String("branch", "test-branch", "Repository branch")
|
testCmd.Flags().String("branch", "test-branch", "Repository branch")
|
||||||
testCmd.Flags().String("config", "test-config", "Config file path")
|
testCmd.Flags().String("config", "test-config", "Config file path")
|
||||||
|
|
||||||
rootCmd = testCmd
|
rootCmd = testCmd
|
||||||
|
|
||||||
// Execute should not panic
|
// Execute should not panic
|
||||||
@@ -82,4 +82,4 @@ func TestSetupCobra(t *testing.T) {
|
|||||||
assertions.Equal(t, "test-branch", testRepo.RepositoryBranch, "Repository branch should be set")
|
assertions.Equal(t, "test-branch", testRepo.RepositoryBranch, "Repository branch should be set")
|
||||||
assertions.Equal(t, "test-config", testRepo.LocalConfigFile, "Config file should be set")
|
assertions.Equal(t, "test-config", testRepo.LocalConfigFile, "Config file should be set")
|
||||||
assertions.True(t, testRepo.UseLocal, "UseLocal should be set to true")
|
assertions.True(t, testRepo.UseLocal, "UseLocal should be set to true")
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -34,18 +34,18 @@ type Config struct {
|
|||||||
// ReadConfig reads the configuration from a file
|
// ReadConfig reads the configuration from a file
|
||||||
func ReadConfig(file string) (*Config, error) {
|
func ReadConfig(file string) (*Config, error) {
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
|
|
||||||
viper.SetConfigFile(file)
|
viper.SetConfigFile(file)
|
||||||
err := viper.ReadInConfig()
|
err := viper.ReadInConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("fatal error config file: %s", err)
|
err = fmt.Errorf("fatal error config file: %s", err)
|
||||||
return config, err
|
return config, err
|
||||||
}
|
}
|
||||||
|
|
||||||
viper.UnmarshalKey("wording", &config.Wording)
|
viper.UnmarshalKey("wording", &config.Wording)
|
||||||
viper.UnmarshalKey("force", &config.Force)
|
viper.UnmarshalKey("force", &config.Force)
|
||||||
viper.UnmarshalKey("blacklist", &config.Blacklist)
|
viper.UnmarshalKey("blacklist", &config.Blacklist)
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,14 +55,14 @@ func ApplyForcedVersioning(force Force, semver *SemVer) {
|
|||||||
Debug("Forced versioning (MAJOR)", map[string]interface{}{"major": force.Major})
|
Debug("Forced versioning (MAJOR)", map[string]interface{}{"major": force.Major})
|
||||||
semver.Major = force.Major
|
semver.Major = force.Major
|
||||||
}
|
}
|
||||||
|
|
||||||
if force.Minor > 0 {
|
if force.Minor > 0 {
|
||||||
Debug("Forced versioning (MINOR)", map[string]interface{}{"minor": force.Minor})
|
Debug("Forced versioning (MINOR)", map[string]interface{}{"minor": force.Minor})
|
||||||
semver.Minor = force.Minor
|
semver.Minor = force.Minor
|
||||||
}
|
}
|
||||||
|
|
||||||
if force.Patch > 0 {
|
if force.Patch > 0 {
|
||||||
Debug("Forced versioning (PATCH)", map[string]interface{}{"patch": force.Patch})
|
Debug("Forced versioning (PATCH)", map[string]interface{}{"patch": force.Patch})
|
||||||
semver.Patch = force.Patch
|
semver.Patch = force.Patch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,4 +198,4 @@ wording:
|
|||||||
// Test reading a non-existent config
|
// Test reading a non-existent config
|
||||||
_, err = ReadConfig("non-existent-file.yaml")
|
_, err = ReadConfig("non-existent-file.yaml")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-28
@@ -29,14 +29,14 @@ type TagDetails struct {
|
|||||||
|
|
||||||
// GitRepository represents a git repository
|
// GitRepository represents a git repository
|
||||||
type GitRepository struct {
|
type GitRepository struct {
|
||||||
Handler *git.Repository
|
Handler *git.Repository
|
||||||
Name string
|
Name string
|
||||||
Branch string
|
Branch string
|
||||||
LocalPath string
|
LocalPath string
|
||||||
UseLocal bool
|
UseLocal bool
|
||||||
Commits []CommitDetails
|
Commits []CommitDetails
|
||||||
Tags []TagDetails
|
Tags []TagDetails
|
||||||
StartCommit string
|
StartCommit string
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareRepository prepares the git repository for use
|
// PrepareRepository prepares the git repository for use
|
||||||
@@ -47,15 +47,15 @@ func PrepareRepository(repo *GitRepository) error {
|
|||||||
u, err := url.Parse(repo.Name)
|
u, err := url.Parse(repo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to parse repository URL", map[string]interface{}{
|
Error("Unable to parse repository URL", map[string]interface{}{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
"url": repo.Name,
|
"url": repo.Name,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.LocalPath = fmt.Sprintf("/tmp/semver/%s/%s", u.Path, repo.Branch)
|
repo.LocalPath = fmt.Sprintf("/tmp/semver/%s/%s", u.Path, repo.Branch)
|
||||||
os.RemoveAll(repo.LocalPath)
|
os.RemoveAll(repo.LocalPath)
|
||||||
|
|
||||||
repo.Handler, err = git.PlainClone(repo.LocalPath, false, &git.CloneOptions{
|
repo.Handler, err = git.PlainClone(repo.LocalPath, false, &git.CloneOptions{
|
||||||
URL: repo.Name,
|
URL: repo.Name,
|
||||||
ReferenceName: plumbing.NewBranchReferenceName(repo.Branch),
|
ReferenceName: plumbing.NewBranchReferenceName(repo.Branch),
|
||||||
@@ -66,11 +66,11 @@ func PrepareRepository(repo *GitRepository) error {
|
|||||||
},
|
},
|
||||||
Tags: git.AllTags,
|
Tags: git.AllTags,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to clone repository", map[string]interface{}{
|
Error("Unable to clone repository", map[string]interface{}{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
"url": repo.Name,
|
"url": repo.Name,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -79,13 +79,13 @@ func PrepareRepository(repo *GitRepository) error {
|
|||||||
repo.Handler, err = git.PlainOpen(repo.LocalPath)
|
repo.Handler, err = git.PlainOpen(repo.LocalPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to open local repository", map[string]interface{}{
|
Error("Unable to open local repository", map[string]interface{}{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
"path": repo.LocalPath,
|
"path": repo.LocalPath,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Chdir(repo.LocalPath)
|
os.Chdir(repo.LocalPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func ListCommits(repo *GitRepository) ([]CommitDetails, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []CommitDetails{}, err
|
return []CommitDetails{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commitsList, err := repo.Handler.Log(&git.LogOptions{From: ref.Hash()})
|
commitsList, err := repo.Handler.Log(&git.LogOptions{From: ref.Hash()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []CommitDetails{}, err
|
return []CommitDetails{}, err
|
||||||
@@ -126,14 +126,14 @@ func ListCommits(repo *GitRepository) ([]CommitDetails, error) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
Debug("Listing commits", map[string]interface{}{"commits": tmpResults})
|
Debug("Listing commits", map[string]interface{}{"commits": tmpResults})
|
||||||
|
|
||||||
// Filter commits starting from the specified commit if provided
|
// Filter commits starting from the specified commit if provided
|
||||||
if repo.StartCommit != "" {
|
if repo.StartCommit != "" {
|
||||||
for commitId, cmt := range tmpResults {
|
for commitId, cmt := range tmpResults {
|
||||||
if cmt.Hash == repo.StartCommit {
|
if cmt.Hash == repo.StartCommit {
|
||||||
Debug("Found commit match", map[string]interface{}{
|
Debug("Found commit match", map[string]interface{}{
|
||||||
"commit": cmt.Hash,
|
"commit": cmt.Hash,
|
||||||
"index": commitId,
|
"index": commitId,
|
||||||
})
|
})
|
||||||
repo.Commits = tmpResults[commitId:]
|
repo.Commits = tmpResults[commitId:]
|
||||||
break
|
break
|
||||||
@@ -150,32 +150,32 @@ func ListCommits(repo *GitRepository) ([]CommitDetails, error) {
|
|||||||
// ListExistingTags lists all tags in the repository
|
// ListExistingTags lists all tags in the repository
|
||||||
func ListExistingTags(repo *GitRepository) {
|
func ListExistingTags(repo *GitRepository) {
|
||||||
Debug("Listing existing tags", nil)
|
Debug("Listing existing tags", nil)
|
||||||
|
|
||||||
// Check if Handler is nil to avoid panic
|
// Check if Handler is nil to avoid panic
|
||||||
if repo.Handler == nil {
|
if repo.Handler == nil {
|
||||||
Debug("Repository handler is nil, skipping tag listing", nil)
|
Debug("Repository handler is nil, skipping tag listing", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
refs, err := repo.Handler.Tags()
|
refs, err := repo.Handler.Tags()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to list tags", map[string]interface{}{"error": err.Error()})
|
Error("Unable to list tags", map[string]interface{}{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := refs.ForEach(func(ref *plumbing.Reference) error {
|
if err := refs.ForEach(func(ref *plumbing.Reference) error {
|
||||||
repo.Tags = append(repo.Tags, TagDetails{
|
repo.Tags = append(repo.Tags, TagDetails{
|
||||||
Name: ref.Name().Short(),
|
Name: ref.Name().Short(),
|
||||||
Hash: ref.Hash().String(),
|
Hash: ref.Hash().String(),
|
||||||
})
|
})
|
||||||
|
|
||||||
Debug("Found tag", map[string]interface{}{
|
Debug("Found tag", map[string]interface{}{
|
||||||
"tag": ref.Name().Short(),
|
"tag": ref.Name().Short(),
|
||||||
"hash": ref.Hash().String(),
|
"hash": ref.Hash().String(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
Error("Error iterating tags", map[string]interface{}{"error": err.Error()})
|
Error("Error iterating tags", map[string]interface{}{"error": err.Error()})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -64,7 +64,7 @@ func TestListCommits(t *testing.T) {
|
|||||||
t.Run("Test commit filtering logic", func(t *testing.T) {
|
t.Run("Test commit filtering logic", func(t *testing.T) {
|
||||||
// Create a test repository with predefined commits
|
// Create a test repository with predefined commits
|
||||||
repo := &GitRepository{}
|
repo := &GitRepository{}
|
||||||
|
|
||||||
// Manually populate the commits for testing
|
// Manually populate the commits for testing
|
||||||
repo.Commits = []CommitDetails{
|
repo.Commits = []CommitDetails{
|
||||||
{
|
{
|
||||||
@@ -83,7 +83,7 @@ func TestListCommits(t *testing.T) {
|
|||||||
|
|
||||||
// Test with StartCommit specified
|
// Test with StartCommit specified
|
||||||
repo.StartCommit = "def456"
|
repo.StartCommit = "def456"
|
||||||
|
|
||||||
// Instead of calling ListCommits which would try to use the nil Handler,
|
// Instead of calling ListCommits which would try to use the nil Handler,
|
||||||
// we'll just test the filtering logic directly
|
// we'll just test the filtering logic directly
|
||||||
if repo.StartCommit != "" {
|
if repo.StartCommit != "" {
|
||||||
@@ -94,19 +94,19 @@ func TestListCommits(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the filtering worked correctly
|
// Verify the filtering worked correctly
|
||||||
assert.Len(t, repo.Commits, 1, "Should filter commits starting from specified hash")
|
assert.Len(t, repo.Commits, 1, "Should filter commits starting from specified hash")
|
||||||
assert.Equal(t, "def456", repo.Commits[0].Hash, "Commit hash should match")
|
assert.Equal(t, "def456", repo.Commits[0].Hash, "Commit hash should match")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test with nil Handler", func(t *testing.T) {
|
t.Run("Test with nil Handler", func(t *testing.T) {
|
||||||
// Create a test repository with nil Handler
|
// Create a test repository with nil Handler
|
||||||
repo := &GitRepository{}
|
repo := &GitRepository{}
|
||||||
|
|
||||||
// Now we can safely call ListCommits since we've added a nil check
|
// Now we can safely call ListCommits since we've added a nil check
|
||||||
commits, err := ListCommits(repo)
|
commits, err := ListCommits(repo)
|
||||||
|
|
||||||
// Verify the function returns without error
|
// Verify the function returns without error
|
||||||
assert.NoError(t, err, "Should not error with nil Handler")
|
assert.NoError(t, err, "Should not error with nil Handler")
|
||||||
assert.Empty(t, commits, "Should return empty commits with nil Handler")
|
assert.Empty(t, commits, "Should return empty commits with nil Handler")
|
||||||
@@ -120,10 +120,10 @@ func TestListExistingTags(t *testing.T) {
|
|||||||
t.Run("Test tag processing", func(t *testing.T) {
|
t.Run("Test tag processing", func(t *testing.T) {
|
||||||
// Create a test repository
|
// Create a test repository
|
||||||
repo := &GitRepository{}
|
repo := &GitRepository{}
|
||||||
|
|
||||||
// Since we can't test the actual git operations, we'll test the function's behavior
|
// Since we can't test the actual git operations, we'll test the function's behavior
|
||||||
// by manually setting up the repository state
|
// by manually setting up the repository state
|
||||||
|
|
||||||
// Manually add tags to verify they're processed correctly
|
// Manually add tags to verify they're processed correctly
|
||||||
repo.Tags = []TagDetails{
|
repo.Tags = []TagDetails{
|
||||||
{
|
{
|
||||||
@@ -131,20 +131,20 @@ func TestListExistingTags(t *testing.T) {
|
|||||||
Hash: "abc123",
|
Hash: "abc123",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Len(t, repo.Tags, 1, "Should have 1 tag")
|
assert.Len(t, repo.Tags, 1, "Should have 1 tag")
|
||||||
assert.Equal(t, "v1.0.0", repo.Tags[0].Name, "Tag name should match")
|
assert.Equal(t, "v1.0.0", repo.Tags[0].Name, "Tag name should match")
|
||||||
assert.Equal(t, "abc123", repo.Tags[0].Hash, "Tag hash should match")
|
assert.Equal(t, "abc123", repo.Tags[0].Hash, "Tag hash should match")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Test with nil Handler", func(t *testing.T) {
|
t.Run("Test with nil Handler", func(t *testing.T) {
|
||||||
// Create a test repository with nil Handler
|
// Create a test repository with nil Handler
|
||||||
repo := &GitRepository{}
|
repo := &GitRepository{}
|
||||||
|
|
||||||
// Now we can safely call ListExistingTags since we've added a nil check
|
// Now we can safely call ListExistingTags since we've added a nil check
|
||||||
ListExistingTags(repo)
|
ListExistingTags(repo)
|
||||||
|
|
||||||
// Verify no tags were added
|
// Verify no tags were added
|
||||||
assert.Empty(t, repo.Tags, "Should have no tags after calling with nil Handler")
|
assert.Empty(t, repo.Tags, "Should have no tags after calling with nil Handler")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -21,7 +21,7 @@ func UpdatePackage() bool {
|
|||||||
|
|
||||||
binaryName := fmt.Sprintf("semver-gen-%s-%s", runtime.GOOS, runtime.GOARCH)
|
binaryName := fmt.Sprintf("semver-gen-%s-%s", runtime.GOOS, runtime.GOARCH)
|
||||||
Info("Checking for updates", map[string]interface{}{"binaryName": binaryName})
|
Info("Checking for updates", map[string]interface{}{"binaryName": binaryName})
|
||||||
|
|
||||||
gql := graphql.NewConnection()
|
gql := graphql.NewConnection()
|
||||||
gql.SetEndpoint("https://api.github.com/graphql")
|
gql.SetEndpoint("https://api.github.com/graphql")
|
||||||
gql.SetOutput("mapstring")
|
gql.SetOutput("mapstring")
|
||||||
@@ -29,11 +29,11 @@ func UpdatePackage() bool {
|
|||||||
headers := map[string]interface{}{
|
headers := map[string]interface{}{
|
||||||
"Authorization": fmt.Sprintf("Bearer %s", ghToken),
|
"Authorization": fmt.Sprintf("Bearer %s", ghToken),
|
||||||
}
|
}
|
||||||
|
|
||||||
variables := map[string]interface{}{
|
variables := map[string]interface{}{
|
||||||
"binaryName": binaryName,
|
"binaryName": binaryName,
|
||||||
}
|
}
|
||||||
|
|
||||||
var query = `query ($binaryName: String) {
|
var query = `query ($binaryName: String) {
|
||||||
repository(name: "semver-generator", owner: "lukaszraczylo") {
|
repository(name: "semver-generator", owner: "lukaszraczylo") {
|
||||||
latestRelease {
|
latestRelease {
|
||||||
@@ -48,7 +48,7 @@ func UpdatePackage() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
result, err := gql.Query(query, variables, headers)
|
result, err := gql.Query(query, variables, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to query GitHub API", map[string]interface{}{"error": err.Error()})
|
Error("Unable to query GitHub API", map[string]interface{}{"error": err.Error()})
|
||||||
@@ -58,12 +58,12 @@ func UpdatePackage() bool {
|
|||||||
output, ok := ask.For(result, "repository.latestRelease.releaseAssets.edges[0].node.downloadUrl").String("")
|
output, ok := ask.For(result, "repository.latestRelease.releaseAssets.edges[0].node.downloadUrl").String("")
|
||||||
if !ok {
|
if !ok {
|
||||||
Error("Unable to obtain download url for the binary", map[string]interface{}{
|
Error("Unable to obtain download url for the binary", map[string]interface{}{
|
||||||
"binary": binaryName,
|
"binary": binaryName,
|
||||||
"output": output,
|
"output": output,
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip actual download in test mode
|
// Skip actual download in test mode
|
||||||
if flag.Lookup("test.v") == nil && os.Getenv("CI") == "" {
|
if flag.Lookup("test.v") == nil && os.Getenv("CI") == "" {
|
||||||
downloadedBinaryPath := fmt.Sprintf("/tmp/%s", binaryName)
|
downloadedBinaryPath := fmt.Sprintf("/tmp/%s", binaryName)
|
||||||
@@ -71,12 +71,12 @@ func UpdatePackage() bool {
|
|||||||
err = g.Download(output, downloadedBinaryPath)
|
err = g.Download(output, downloadedBinaryPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to download binary", map[string]interface{}{
|
Error("Unable to download binary", map[string]interface{}{
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
"binaryPath": downloadedBinaryPath,
|
"binaryPath": downloadedBinaryPath,
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
currentBinary, err := os.Executable()
|
currentBinary, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to obtain current binary path", map[string]interface{}{
|
Error("Unable to obtain current binary path", map[string]interface{}{
|
||||||
@@ -84,7 +84,7 @@ func UpdatePackage() bool {
|
|||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Rename(downloadedBinaryPath, currentBinary)
|
err = os.Rename(downloadedBinaryPath, currentBinary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to overwrite current binary", map[string]interface{}{
|
Error("Unable to overwrite current binary", map[string]interface{}{
|
||||||
@@ -92,7 +92,7 @@ func UpdatePackage() bool {
|
|||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Chmod(currentBinary, 0777)
|
err = os.Chmod(currentBinary, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to make binary executable", map[string]interface{}{
|
Error("Unable to make binary executable", map[string]interface{}{
|
||||||
@@ -101,7 +101,7 @@ func UpdatePackage() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,16 +111,16 @@ func CheckLatestRelease() (string, bool) {
|
|||||||
if !ghTokenSet {
|
if !ghTokenSet {
|
||||||
return "[no GITHUB_TOKEN set]", false
|
return "[no GITHUB_TOKEN set]", false
|
||||||
}
|
}
|
||||||
|
|
||||||
gql := graphql.NewConnection()
|
gql := graphql.NewConnection()
|
||||||
gql.SetEndpoint("https://api.github.com/graphql")
|
gql.SetEndpoint("https://api.github.com/graphql")
|
||||||
|
|
||||||
headers := map[string]interface{}{
|
headers := map[string]interface{}{
|
||||||
"Authorization": fmt.Sprintf("bearer %s", ghToken),
|
"Authorization": fmt.Sprintf("bearer %s", ghToken),
|
||||||
}
|
}
|
||||||
|
|
||||||
variables := map[string]interface{}{}
|
variables := map[string]interface{}{}
|
||||||
|
|
||||||
var query = `query {
|
var query = `query {
|
||||||
repository(name: "semver-generator", owner: "lukaszraczylo", followRenames: true) {
|
repository(name: "semver-generator", owner: "lukaszraczylo", followRenames: true) {
|
||||||
releases(last: 2) {
|
releases(last: 2) {
|
||||||
@@ -132,17 +132,17 @@ func CheckLatestRelease() (string, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
result, err := gql.Query(query, variables, headers)
|
result, err := gql.Query(query, variables, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Unable to query GitHub API", map[string]interface{}{"error": err.Error()})
|
Error("Unable to query GitHub API", map[string]interface{}{"error": err.Error()})
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
output, _ := ask.For(result, "repository.releases.nodes[0].tag.name").String("")
|
output, _ := ask.For(result, "repository.releases.nodes[0].tag.name").String("")
|
||||||
if output == "v1" {
|
if output == "v1" {
|
||||||
output, _ = ask.For(result, "repository.releases.nodes[1].tag.name").String("")
|
output, _ = ask.For(result, "repository.releases.nodes[1].tag.name").String("")
|
||||||
}
|
}
|
||||||
|
|
||||||
return output, true
|
return output, true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ func TestUpdatePackage(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: We're not using mock transports for these tests to avoid
|
// Note: We're not using mock transports for these tests to avoid
|
||||||
// adding complexity. The tests focus on the token presence logic and error handling.
|
// adding complexity. The tests focus on the token presence logic and error handling.
|
||||||
|
|||||||
@@ -56,4 +56,4 @@ func Critical(message string, pairs map[string]interface{}) {
|
|||||||
Pairs: pairs,
|
Pairs: pairs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitLogger(t *testing.T) {
|
func TestInitLogger(t *testing.T) {
|
||||||
// Test with debug mode enabled
|
// Test with debug mode enabled
|
||||||
logger := InitLogger(true)
|
logger := InitLogger(true)
|
||||||
@@ -25,10 +26,10 @@ func TestLoggingFunctions(t *testing.T) {
|
|||||||
Debug("Debug message", map[string]interface{}{"key": "value"})
|
Debug("Debug message", map[string]interface{}{"key": "value"})
|
||||||
Info("Info message", map[string]interface{}{"key": "value"})
|
Info("Info message", map[string]interface{}{"key": "value"})
|
||||||
Error("Error message", map[string]interface{}{"key": "value"})
|
Error("Error message", map[string]interface{}{"key": "value"})
|
||||||
|
|
||||||
// Skip testing Critical as it might call os.Exit
|
// Skip testing Critical as it might call os.Exit
|
||||||
// Critical("Critical message", map[string]interface{}{"key": "value"})
|
// Critical("Critical message", map[string]interface{}{"key": "value"})
|
||||||
|
|
||||||
// Test passes if we get here without panicking
|
// Test passes if we get here without panicking
|
||||||
assert.True(t, true)
|
assert.True(t, true)
|
||||||
}
|
}
|
||||||
@@ -43,10 +44,10 @@ func TestLoggingWithNilLogger(t *testing.T) {
|
|||||||
Debug("Debug message", map[string]interface{}{"key": "value"})
|
Debug("Debug message", map[string]interface{}{"key": "value"})
|
||||||
Info("Info message", map[string]interface{}{"key": "value"})
|
Info("Info message", map[string]interface{}{"key": "value"})
|
||||||
Error("Error message", map[string]interface{}{"key": "value"})
|
Error("Error message", map[string]interface{}{"key": "value"})
|
||||||
|
|
||||||
// Skip testing Critical as it might call os.Exit
|
// Skip testing Critical as it might call os.Exit
|
||||||
// Critical("Critical message", map[string]interface{}{"key": "value"})
|
// Critical("Critical message", map[string]interface{}{"key": "value"})
|
||||||
|
|
||||||
// Test passes if we get here without panicking
|
// Test passes if we get here without panicking
|
||||||
assert.True(t, true)
|
assert.True(t, true)
|
||||||
}
|
}
|
||||||
@@ -56,15 +57,15 @@ func TestCriticalNilLogger(t *testing.T) {
|
|||||||
// Save original logger and restore after test
|
// Save original logger and restore after test
|
||||||
originalLogger := Logger
|
originalLogger := Logger
|
||||||
defer func() { Logger = originalLogger }()
|
defer func() { Logger = originalLogger }()
|
||||||
|
|
||||||
// Set logger to nil
|
// Set logger to nil
|
||||||
Logger = nil
|
Logger = nil
|
||||||
|
|
||||||
// This should not panic
|
// This should not panic
|
||||||
Critical("Critical message", map[string]interface{}{"key": "value"})
|
Critical("Critical message", map[string]interface{}{"key": "value"})
|
||||||
|
|
||||||
// Test passes if we get here without panicking
|
// Test passes if we get here without panicking
|
||||||
assert.True(t, true)
|
assert.True(t, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: We don't test Critical with an actual logger because it calls os.Exit
|
// Note: We don't test Critical with an actual logger because it calls os.Exit
|
||||||
|
|||||||
+11
-11
@@ -22,7 +22,7 @@ func CalculateSemver(
|
|||||||
for _, tagHash := range tags {
|
for _, tagHash := range tags {
|
||||||
if commit.Hash == tagHash.Hash {
|
if commit.Hash == tagHash.Hash {
|
||||||
Debug("Found existing tag", map[string]interface{}{
|
Debug("Found existing tag", map[string]interface{}{
|
||||||
"tag": tagHash.Name,
|
"tag": tagHash.Name,
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
})
|
})
|
||||||
semver = ParseExistingSemver(tagHash.Name, semver)
|
semver = ParseExistingSemver(tagHash.Name, semver)
|
||||||
@@ -35,7 +35,7 @@ func CalculateSemver(
|
|||||||
if !strictMode {
|
if !strictMode {
|
||||||
semver.Patch++
|
semver.Patch++
|
||||||
Debug("Incrementing patch (DEFAULT)", map[string]interface{}{
|
Debug("Incrementing patch (DEFAULT)", map[string]interface{}{
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
"semver": FormatSemver(semver),
|
"semver": FormatSemver(semver),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,44 +55,44 @@ func CalculateSemver(
|
|||||||
semver.EnableReleaseCandidate = false
|
semver.EnableReleaseCandidate = false
|
||||||
semver.Release = 0
|
semver.Release = 0
|
||||||
Debug("Incrementing major (WORDING)", map[string]interface{}{
|
Debug("Incrementing major (WORDING)", map[string]interface{}{
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
"semver": FormatSemver(semver),
|
"semver": FormatSemver(semver),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchMinor {
|
if matchMinor {
|
||||||
semver.Minor++
|
semver.Minor++
|
||||||
semver.Patch = 1
|
semver.Patch = 1
|
||||||
semver.EnableReleaseCandidate = false
|
semver.EnableReleaseCandidate = false
|
||||||
semver.Release = 0
|
semver.Release = 0
|
||||||
Debug("Incrementing minor (WORDING)", map[string]interface{}{
|
Debug("Incrementing minor (WORDING)", map[string]interface{}{
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
"semver": FormatSemver(semver),
|
"semver": FormatSemver(semver),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchReleaseCandidate {
|
if matchReleaseCandidate {
|
||||||
semver.Release++
|
semver.Release++
|
||||||
semver.Patch = 1
|
semver.Patch = 1
|
||||||
semver.EnableReleaseCandidate = true
|
semver.EnableReleaseCandidate = true
|
||||||
Debug("Incrementing release candidate (WORDING)", map[string]interface{}{
|
Debug("Incrementing release candidate (WORDING)", map[string]interface{}{
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
"semver": FormatSemver(semver),
|
"semver": FormatSemver(semver),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchPatch {
|
if matchPatch {
|
||||||
semver.Patch++
|
semver.Patch++
|
||||||
Debug("Incrementing patch (WORDING)", map[string]interface{}{
|
Debug("Incrementing patch (WORDING)", map[string]interface{}{
|
||||||
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
"commit": strings.TrimSuffix(commit.Message, "\n"),
|
||||||
"semver": FormatSemver(semver),
|
"semver": FormatSemver(semver),
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return semver
|
return semver
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -19,7 +19,7 @@ func TestCalculateSemver(t *testing.T) {
|
|||||||
// More sophisticated mock implementation for testing
|
// More sophisticated mock implementation for testing
|
||||||
for _, h := range haystack {
|
for _, h := range haystack {
|
||||||
// Check for substring match to better simulate fuzzy search
|
// Check for substring match to better simulate fuzzy search
|
||||||
if h == needle || (len(h) >= 3 && len(needle) >= 3 &&
|
if h == needle || (len(h) >= 3 && len(needle) >= 3 &&
|
||||||
(h[:3] == needle[:3] || h[len(h)-3:] == needle[len(needle)-3:])) {
|
(h[:3] == needle[:3] || h[len(h)-3:] == needle[len(needle)-3:])) {
|
||||||
return []string{h}
|
return []string{h}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ func TestCalculateSemver(t *testing.T) {
|
|||||||
|
|
||||||
// Test data
|
// Test data
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
// Common wording and blacklist for all tests
|
// Common wording and blacklist for all tests
|
||||||
wording := Wording{
|
wording := Wording{
|
||||||
Patch: []string{"update", "fix", "initial"},
|
Patch: []string{"update", "fix", "initial"},
|
||||||
@@ -77,10 +77,10 @@ func TestCalculateSemver(t *testing.T) {
|
|||||||
respectExisting: true,
|
respectExisting: true,
|
||||||
strictMode: false,
|
strictMode: false,
|
||||||
want: SemVer{
|
want: SemVer{
|
||||||
Major: 2,
|
Major: 2,
|
||||||
Minor: 0,
|
Minor: 0,
|
||||||
Patch: 1, // Initial tag 2.0.0 + one patch increment
|
Patch: 1, // Initial tag 2.0.0 + one patch increment
|
||||||
Release: 1,
|
Release: 1,
|
||||||
EnableReleaseCandidate: true,
|
EnableReleaseCandidate: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -110,10 +110,10 @@ func TestCalculateSemver(t *testing.T) {
|
|||||||
respectExisting: true,
|
respectExisting: true,
|
||||||
strictMode: true,
|
strictMode: true,
|
||||||
want: SemVer{
|
want: SemVer{
|
||||||
Major: 2,
|
Major: 2,
|
||||||
Minor: 0,
|
Minor: 0,
|
||||||
Patch: 1, // Initial tag 2.0.0 + patch from "update" keyword
|
Patch: 1, // Initial tag 2.0.0 + patch from "update" keyword
|
||||||
Release: 1,
|
Release: 1,
|
||||||
EnableReleaseCandidate: true,
|
EnableReleaseCandidate: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -254,4 +254,4 @@ func TestCalculateSemver(t *testing.T) {
|
|||||||
assert.Equal(t, tt.want.EnableReleaseCandidate, got.EnableReleaseCandidate, "EnableReleaseCandidate mismatch")
|
assert.Equal(t, tt.want.EnableReleaseCandidate, got.EnableReleaseCandidate, "EnableReleaseCandidate mismatch")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-13
@@ -54,33 +54,33 @@ var extractNumber = regexp.MustCompile("[0-9]+")
|
|||||||
// ParseExistingSemver parses a semantic version from a tag name
|
// ParseExistingSemver parses a semantic version from a tag name
|
||||||
func ParseExistingSemver(tagName string, currentSemver SemVer) SemVer {
|
func ParseExistingSemver(tagName string, currentSemver SemVer) SemVer {
|
||||||
Debug("Parsing existing semver", map[string]interface{}{"tag": tagName})
|
Debug("Parsing existing semver", map[string]interface{}{"tag": tagName})
|
||||||
|
|
||||||
tagNameParts := strings.Split(tagName, ".")
|
tagNameParts := strings.Split(tagName, ".")
|
||||||
if len(tagNameParts) < 3 {
|
if len(tagNameParts) < 3 {
|
||||||
Debug("Unable to parse incompatible semver (non x.y.z)", map[string]interface{}{"tag": tagName})
|
Debug("Unable to parse incompatible semver (non x.y.z)", map[string]interface{}{"tag": tagName})
|
||||||
return currentSemver
|
return currentSemver
|
||||||
}
|
}
|
||||||
|
|
||||||
semanticVersion := SemVer{}
|
semanticVersion := SemVer{}
|
||||||
|
|
||||||
// Extract major version
|
// Extract major version
|
||||||
majorMatches := extractNumber.FindAllString(tagNameParts[0], -1)
|
majorMatches := extractNumber.FindAllString(tagNameParts[0], -1)
|
||||||
if len(majorMatches) > 0 {
|
if len(majorMatches) > 0 {
|
||||||
semanticVersion.Major, _ = strconv.Atoi(majorMatches[0])
|
semanticVersion.Major, _ = strconv.Atoi(majorMatches[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract minor version
|
// Extract minor version
|
||||||
minorMatches := extractNumber.FindAllString(tagNameParts[1], -1)
|
minorMatches := extractNumber.FindAllString(tagNameParts[1], -1)
|
||||||
if len(minorMatches) > 0 {
|
if len(minorMatches) > 0 {
|
||||||
semanticVersion.Minor, _ = strconv.Atoi(minorMatches[0])
|
semanticVersion.Minor, _ = strconv.Atoi(minorMatches[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract patch version
|
// Extract patch version
|
||||||
patchMatches := extractNumber.FindAllString(tagNameParts[2], -1)
|
patchMatches := extractNumber.FindAllString(tagNameParts[2], -1)
|
||||||
if len(patchMatches) > 0 {
|
if len(patchMatches) > 0 {
|
||||||
semanticVersion.Patch, _ = strconv.Atoi(patchMatches[0])
|
semanticVersion.Patch, _ = strconv.Atoi(patchMatches[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract release candidate version if present
|
// Extract release candidate version if present
|
||||||
if len(tagNameParts) > 3 {
|
if len(tagNameParts) > 3 {
|
||||||
releaseMatches := extractNumber.FindAllString(tagNameParts[3], -1)
|
releaseMatches := extractNumber.FindAllString(tagNameParts[3], -1)
|
||||||
@@ -89,14 +89,14 @@ func ParseExistingSemver(tagName string, currentSemver SemVer) SemVer {
|
|||||||
semanticVersion.EnableReleaseCandidate = true
|
semanticVersion.EnableReleaseCandidate = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return semanticVersion
|
return semanticVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckMatches checks if any of the targets match the content
|
// CheckMatches checks if any of the targets match the content
|
||||||
func CheckMatches(content []string, targets []string, blacklist []string) bool {
|
func CheckMatches(content []string, targets []string, blacklist []string) bool {
|
||||||
contentStr := strings.Join(content, " ")
|
contentStr := strings.Join(content, " ")
|
||||||
|
|
||||||
// First check if any target matches
|
// First check if any target matches
|
||||||
hasMatch := false
|
hasMatch := false
|
||||||
for _, tgt := range targets {
|
for _, tgt := range targets {
|
||||||
@@ -104,8 +104,8 @@ func CheckMatches(content []string, targets []string, blacklist []string) bool {
|
|||||||
if len(matches) > 0 {
|
if len(matches) > 0 {
|
||||||
hasMatch = true
|
hasMatch = true
|
||||||
Debug("Found match", map[string]interface{}{
|
Debug("Found match", map[string]interface{}{
|
||||||
"target": tgt,
|
"target": tgt,
|
||||||
"match": strings.Join(matches, ","),
|
"match": strings.Join(matches, ","),
|
||||||
"content": contentStr,
|
"content": contentStr,
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
@@ -117,14 +117,14 @@ func CheckMatches(content []string, targets []string, blacklist []string) bool {
|
|||||||
for _, blacklistTerm := range blacklist {
|
for _, blacklistTerm := range blacklist {
|
||||||
if strings.Contains(strings.ToLower(contentStr), strings.ToLower(blacklistTerm)) {
|
if strings.Contains(strings.ToLower(contentStr), strings.ToLower(blacklistTerm)) {
|
||||||
Debug("Blacklisted term detected, ignoring commit", map[string]interface{}{
|
Debug("Blacklisted term detected, ignoring commit", map[string]interface{}{
|
||||||
"content": contentStr,
|
"content": contentStr,
|
||||||
"blacklist_term": blacklistTerm,
|
"blacklist_term": blacklistTerm,
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasMatch
|
return hasMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,4 +132,4 @@ func CheckMatches(content []string, targets []string, blacklist []string) bool {
|
|||||||
var FuzzyFind = func(needle string, haystack []string) []string {
|
var FuzzyFind = func(needle string, haystack []string) []string {
|
||||||
// This will be replaced with the actual implementation in main.go
|
// This will be replaced with the actual implementation in main.go
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -58,14 +58,14 @@ func TestParseExistingSemver(t *testing.T) {
|
|||||||
InitLogger(false)
|
InitLogger(false)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
tagName string
|
tagName string
|
||||||
currentSemver SemVer
|
currentSemver SemVer
|
||||||
want SemVer
|
want SemVer
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Standard semver",
|
name: "Standard semver",
|
||||||
tagName: "1.2.3",
|
tagName: "1.2.3",
|
||||||
currentSemver: SemVer{},
|
currentSemver: SemVer{},
|
||||||
want: SemVer{
|
want: SemVer{
|
||||||
Major: 1,
|
Major: 1,
|
||||||
@@ -74,8 +74,8 @@ func TestParseExistingSemver(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With v prefix",
|
name: "With v prefix",
|
||||||
tagName: "v2.3.4",
|
tagName: "v2.3.4",
|
||||||
currentSemver: SemVer{},
|
currentSemver: SemVer{},
|
||||||
want: SemVer{
|
want: SemVer{
|
||||||
Major: 2,
|
Major: 2,
|
||||||
@@ -84,8 +84,8 @@ func TestParseExistingSemver(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "With release candidate",
|
name: "With release candidate",
|
||||||
tagName: "3.4.5-rc.2",
|
tagName: "3.4.5-rc.2",
|
||||||
currentSemver: SemVer{},
|
currentSemver: SemVer{},
|
||||||
want: SemVer{
|
want: SemVer{
|
||||||
Major: 3,
|
Major: 3,
|
||||||
@@ -196,4 +196,4 @@ func TestCheckMatches(t *testing.T) {
|
|||||||
assert.Equal(t, tt.want, got)
|
assert.Equal(t, tt.want, got)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -30,4 +30,4 @@ func TestMain(t *testing.T) {
|
|||||||
|
|
||||||
// Verify that the version was set correctly
|
// Verify that the version was set correctly
|
||||||
assert.Equal(t, "test-version", cmd.PKG_VERSION, "PKG_VERSION should be set correctly")
|
assert.Equal(t, "test-version", cmd.PKG_VERSION, "PKG_VERSION should be set correctly")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user