From 1e0c77aa248862f29e15f668a055c98a1bcb6965 Mon Sep 17 00:00:00 2001 From: sxwebdev Date: Mon, 17 Mar 2025 09:12:03 +0300 Subject: [PATCH] generating changelog --- README.md | 56 ++++++++++++++++---------------- cmd/gcx/main.go | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 070a189..2e2f0f8 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ COMMANDS: build Compiles binaries publish Publishes artifacts based on the configuration deploy Deploys artifacts based on the configuration + release Release related commands git Git related commands version Displays the current version help, h Shows a list of commands or help for one command @@ -247,45 +248,44 @@ Error: command 'systemctl start myapp' failed: exit status 1 Once installed, you can run the following commands: -- **Build binaries:** - - ```bash - gcx build --config gcx.yaml - ``` +```bash +# Build binaries according to configuration +gcx build - This command: +# Publish artifacts to configured destinations +gcx publish - 1. Runs pre-build hooks - 2. Compiles binaries for specified targets - 3. Creates archives if configured - 4. Runs post-build hooks - 5. Stores results in the output directory +# Deploy artifacts using configured deployment settings +gcx deploy +gcx deploy --name production # Deploy specific configuration -- **Publish artifacts:** +# Show current git tag version +gcx git version - ```bash - gcx publish --config gcx.yaml - ``` +# Generate a changelog between current and previous git tags +gcx release changelog - Uploads all files from the output directory to configured destinations (S3 or SSH). +# Show gcx version information +gcx version +``` -- **Deploy:** +The changelog command generates a markdown-formatted list of changes between the current and previous git tags, including: - ```bash - # Deploy all configurations - gcx deploy --config gcx.yaml +- List of changes with commit messages +- Author of each change +- Short commit hash +- Full changelog comparison URL - # Deploy specific configuration - gcx deploy --config gcx.yaml --name production - ``` +Example changelog output: - Executes deployment commands on target servers via SSH. +```markdown +## What's Changed -- **Show version:** +- Add new feature by @author in abc1234 +- Fix documentation by @another-author in def5678 - ```bash - gcx version - ``` +**Full Changelog**: https://github.com/user/repo/compare/v0.0.1...v0.0.2 +``` ## GitLab CI/CD Integration Example diff --git a/cmd/gcx/main.go b/cmd/gcx/main.go index 9315d82..5b46959 100644 --- a/cmd/gcx/main.go +++ b/cmd/gcx/main.go @@ -221,6 +221,70 @@ func getGitTag() string { return tag } +// getPreviousGitTag returns the previous git tag before the current one +func getPreviousGitTag() string { + // Get all tags sorted by version + cmd := exec.Command("git", "tag", "-l", "--sort=-v:refname") + out, err := cmd.Output() + if err != nil { + log.Printf("Failed to get git tags: %v. Using default value 0.0.0", err) + return "0.0.0" + } + + tags := strings.Split(strings.TrimSpace(string(out)), "\n") + if len(tags) < 2 { + log.Println("No previous tag found, using default value 0.0.0") + return "0.0.0" + } + + // Current tag should be the first one, so return the second one + currentTag := getGitTag() + for i, tag := range tags { + if tag == currentTag && i+1 < len(tags) { + return tags[i+1] + } + } + + return "0.0.0" +} + +// getGitChangelog returns a markdown formatted changelog between two tags +func getGitChangelog(from, to string) (string, error) { + // Get the repository URL + remoteCmd := exec.Command("git", "config", "--get", "remote.origin.url") + remoteOut, err := remoteCmd.Output() + if err != nil { + return "", fmt.Errorf("failed to get remote URL: %w", err) + } + + // Convert SSH URL to HTTPS URL if necessary + repoURL := strings.TrimSpace(string(remoteOut)) + repoURL = strings.TrimSuffix(repoURL, ".git") + if strings.HasPrefix(repoURL, "git@") { + repoURL = strings.Replace(repoURL, ":", "/", 1) + repoURL = strings.Replace(repoURL, "git@", "https://", 1) + } + + // Get all commits between tags + cmd := exec.Command("git", "log", + "--pretty=format:* %s by @%an in %h", // Format each commit as a markdown list item with author and short hash + fmt.Sprintf("%s..%s", from, to)) // From older to newer tag + out, err := cmd.Output() + if err != nil { + return "", fmt.Errorf("failed to get git log: %w", err) + } + + // Create the final markdown + var sb strings.Builder + sb.WriteString("## What's Changed\n\n") + sb.WriteString(string(out) + "\n") + sb.WriteString("\n") + sb.WriteString(fmt.Sprintf("**Full Changelog**: %s/compare/%s...%s\n", + repoURL, from, to)) + + return sb.String(), nil +} + // buildBinaries performs cross-compilation of binaries according to the configuration. func buildBinaries(cfg *Config) error { // Execute hooks (e.g., "go mod tidy") @@ -839,6 +903,28 @@ func main() { return deployArtifacts(cfg, c.String("name")) }, }, + { + Name: "release", + Usage: "Release related commands", + Subcommands: []*cli.Command{ + { + Name: "changelog", + Usage: "Generate a changelog between the current and previous git tags", + Action: func(c *cli.Context) error { + currentTag := getGitTag() + previousTag := getPreviousGitTag() + + changelog, err := getGitChangelog(previousTag, currentTag) + if err != nil { + return fmt.Errorf("failed to generate changelog: %w", err) + } + + fmt.Println(changelog) + return nil + }, + }, + }, + }, { Name: "git", Usage: "Git related commands",