Skip to content

Commit f174d71

Browse files
authored
Merge pull request #6 from ClouGence/codex/version-profiles-release-0-1-2
[codex] add version info, profiles, and release packaging
2 parents 1b430ae + dc5b558 commit f174d71

25 files changed

Lines changed: 1427 additions & 257 deletions

.github/workflows/release.yml

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -25,41 +25,10 @@ jobs:
2525

2626
- name: Build release assets
2727
run: |
28-
set -euo pipefail
29-
mkdir -p dist
30-
VERSION="${GITHUB_REF_NAME:-dev}"
31-
for target in \
32-
"darwin amd64" \
33-
"darwin arm64" \
34-
"linux amd64" \
35-
"linux arm64"
36-
do
37-
read -r goos goarch <<<"$target"
38-
workdir="$(mktemp -d)"
39-
asset_name="cloudcanal_${goos}_${goarch}.tar.gz"
40-
GOOS="$goos" GOARCH="$goarch" CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o "$workdir/cloudcanal" ./cmd/cloudcanal
41-
tar -C "$workdir" -czf "dist/$asset_name" cloudcanal
42-
rm -rf "$workdir"
43-
done
44-
(
45-
cd dist
46-
sha256sum cloudcanal_*.tar.gz > checksums.txt
47-
)
48-
49-
- name: Generate release notes from CHANGELOG
50-
run: |
51-
set -euo pipefail
52-
version="${GITHUB_REF_NAME#v}"
53-
output="dist/release-notes.md"
54-
awk -v version="$version" '
55-
$0 ~ "^## \\[" version "\\]" { in_section = 1 }
56-
/^## \[/ && in_section && $0 !~ "^## \\[" version "\\]" { exit }
57-
in_section { print }
58-
' CHANGELOG.md > "$output"
59-
60-
if [[ ! -s "$output" ]]; then
61-
echo "Release notes for version ${version} not found in CHANGELOG.md" >&2
62-
exit 1
28+
if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then
29+
VERSION="${GITHUB_REF_NAME#v}" make release-assets
30+
else
31+
make release-assets
6332
fi
6433
6534
- name: Publish GitHub Release
@@ -68,4 +37,7 @@ jobs:
6837
files: |
6938
dist/cloudcanal_*.tar.gz
7039
dist/checksums.txt
40+
dist/install.sh
41+
dist/uninstall.sh
42+
dist/release-notes.md
7143
body_path: dist/release-notes.md

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [0.1.2] - 2026-04-02
6+
7+
### Added
8+
9+
- Added `version` and `--version` commands with `version`, `commit`, and `buildTime` output.
10+
- Added profile-aware configuration management with `config profiles list|use|add|remove`.
11+
- Added build metadata injection and release asset packaging via a shared `make release-assets` flow.
12+
13+
### Changed
14+
15+
- Switched CLI configuration storage to `language + currentProfile + profiles` schema under `~/.cloudcanal-cli/config.json`.
16+
- Updated `config show`, REPL prompt, help text, completion, and docs to expose the active profile context.
17+
- Enhanced release delivery to publish installer assets and print installed build metadata after installation.
18+
19+
### Removed
20+
21+
- Removed support for silently reusing the legacy single-profile config format; users are now prompted to reinitialize into the profile-based schema.
22+
523
## [0.1.1] - 2026-04-02
624

725
### Changed

Makefile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,20 @@ BIN ?= bin/cloudcanal
33
PKG ?= ./...
44
TEST_PKG ?= ./test/...
55
COVER_PROFILE ?= coverage.out
6+
DIST_DIR ?= dist
7+
VERSION ?= dev
8+
COMMIT ?= $(shell git rev-parse HEAD 2>/dev/null || echo unknown)
9+
BUILD_TIME ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
10+
GO_BUILD_FLAGS ?=
11+
EXTRA_LDFLAGS ?=
12+
BUILDINFO_PKG := github.com/ClouGence/cloudcanal-openapi-cli/internal/buildinfo
13+
LDFLAGS ?= -X $(BUILDINFO_PKG).Version=$(VERSION) -X $(BUILDINFO_PKG).Commit=$(COMMIT) -X $(BUILDINFO_PKG).BuildTime=$(BUILD_TIME) $(EXTRA_LDFLAGS)
614

7-
.PHONY: build test vet test-race cover ci clean
15+
.PHONY: build test vet test-race cover ci release-assets clean
816

917
build:
1018
mkdir -p $(dir $(BIN))
11-
$(GO) build -o $(BIN) ./cmd/cloudcanal
19+
$(GO) build $(GO_BUILD_FLAGS) -ldflags "$(LDFLAGS)" -o $(BIN) ./cmd/cloudcanal
1220

1321
test:
1422
$(GO) test $(PKG)
@@ -25,5 +33,8 @@ cover:
2533

2634
ci: test vet test-race cover build
2735

36+
release-assets:
37+
./scripts/build_release_assets.sh
38+
2839
clean:
29-
rm -rf $(dir $(BIN)) $(COVER_PROFILE)
40+
rm -rf $(dir $(BIN)) $(DIST_DIR) $(COVER_PROFILE)

README.md

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ cloudcanal
3434
单次命令:
3535

3636
```bash
37+
cloudcanal version
38+
cloudcanal --version
3739
cloudcanal --help
3840
cloudcanal jobs --help
41+
cloudcanal config profiles list
42+
cloudcanal config profiles use dev
43+
cloudcanal config profiles add test
3944
cloudcanal config lang set zh
4045
cloudcanal jobs list
4146
cloudcanal jobs show 123
@@ -64,20 +69,29 @@ cloudcanal jobs list --type SYNC --output json
6469

6570
```json
6671
{
67-
"apiBaseUrl": "https://cc.example.com",
68-
"accessKey": "your-ak",
69-
"secretKey": "your-sk",
70-
"language": "en"
72+
"language": "en",
73+
"currentProfile": "dev",
74+
"profiles": {
75+
"dev": {
76+
"apiBaseUrl": "https://cc.example.com",
77+
"accessKey": "your-ak",
78+
"secretKey": "your-sk"
79+
}
80+
}
7181
}
7282
```
7383

74-
如果你需要调整网络行为,也可以追加这些可选项
84+
如果你需要调整网络行为,也可以在具体 profile 下追加这些可选项
7585

7686
```json
7787
{
78-
"httpTimeoutSeconds": 15,
79-
"httpReadMaxRetries": 2,
80-
"httpReadRetryBackoffMillis": 300
88+
"profiles": {
89+
"dev": {
90+
"httpTimeoutSeconds": 15,
91+
"httpReadMaxRetries": 2,
92+
"httpReadRetryBackoffMillis": 300
93+
}
94+
}
8195
}
8296
```
8397

cmd/cloudcanal/main.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package main
22

33
import (
4+
"encoding/json"
5+
"errors"
46
"fmt"
57
"os"
68
"strings"
79

810
"github.com/ClouGence/cloudcanal-openapi-cli/internal/app"
11+
"github.com/ClouGence/cloudcanal-openapi-cli/internal/buildinfo"
912
"github.com/ClouGence/cloudcanal-openapi-cli/internal/config"
1013
"github.com/ClouGence/cloudcanal-openapi-cli/internal/console"
1114
"github.com/ClouGence/cloudcanal-openapi-cli/internal/i18n"
@@ -61,6 +64,9 @@ func handleEarlyCommands(args []string) (bool, int) {
6164
fmt.Println(helpText)
6265
return true, 0
6366
}
67+
if handled, exitCode := handleVersionCommand(args); handled {
68+
return true, exitCode
69+
}
6470

6571
if len(args) == 0 {
6672
return false, 0
@@ -84,3 +90,112 @@ func handleEarlyCommands(args []string) (bool, int) {
8490
return false, 0
8591
}
8692
}
93+
94+
func handleVersionCommand(args []string) (bool, int) {
95+
filtered, format, err := extractOutputFormat(args)
96+
if err != nil {
97+
fmt.Fprintln(os.Stderr, err.Error())
98+
return true, 1
99+
}
100+
if len(filtered) == 0 {
101+
return false, 0
102+
}
103+
104+
switch {
105+
case len(filtered) == 1 && strings.EqualFold(filtered[0], "--version"):
106+
return true, printVersion(format)
107+
case strings.EqualFold(filtered[0], "version"):
108+
if len(filtered) != 1 {
109+
fmt.Fprintln(os.Stderr, versionUsageText())
110+
return true, 1
111+
}
112+
return true, printVersion(format)
113+
case containsVersionFlag(filtered):
114+
fmt.Fprintln(os.Stderr, versionFlagErrorText())
115+
return true, 1
116+
default:
117+
return false, 0
118+
}
119+
}
120+
121+
func printVersion(format string) int {
122+
info := buildinfo.Current()
123+
if format == "json" {
124+
data, err := json.MarshalIndent(info, "", " ")
125+
if err != nil {
126+
fmt.Fprintln(os.Stderr, err.Error())
127+
return 1
128+
}
129+
fmt.Println(string(data))
130+
return 0
131+
}
132+
133+
fmt.Println("version: " + info.Version)
134+
fmt.Println("commit: " + info.Commit)
135+
fmt.Println("buildTime: " + info.BuildTime)
136+
return 0
137+
}
138+
139+
func extractOutputFormat(args []string) ([]string, string, error) {
140+
format := "text"
141+
filtered := make([]string, 0, len(args))
142+
seen := false
143+
144+
for i := 0; i < len(args); i++ {
145+
token := args[i]
146+
switch {
147+
case token == "--output":
148+
if i+1 >= len(args) {
149+
return nil, "", errors.New(i18n.T("parser.outputOptionRequiresValue"))
150+
}
151+
if seen {
152+
return nil, "", errors.New(i18n.T("parser.duplicateOption", "output"))
153+
}
154+
value := strings.ToLower(strings.TrimSpace(args[i+1]))
155+
if value != "text" && value != "json" {
156+
return nil, "", errors.New(i18n.T("parser.outputOptionInvalid"))
157+
}
158+
format = value
159+
seen = true
160+
i++
161+
case strings.HasPrefix(token, "--output="):
162+
if seen {
163+
return nil, "", errors.New(i18n.T("parser.duplicateOption", "output"))
164+
}
165+
_, value, _ := strings.Cut(token, "=")
166+
value = strings.ToLower(strings.TrimSpace(value))
167+
if value != "text" && value != "json" {
168+
return nil, "", errors.New(i18n.T("parser.outputOptionInvalid"))
169+
}
170+
format = value
171+
seen = true
172+
default:
173+
filtered = append(filtered, token)
174+
}
175+
}
176+
177+
return filtered, format, nil
178+
}
179+
180+
func containsVersionFlag(args []string) bool {
181+
for _, arg := range args {
182+
if strings.EqualFold(arg, "--version") {
183+
return true
184+
}
185+
}
186+
return false
187+
}
188+
189+
func versionUsageText() string {
190+
if i18n.CurrentLanguage() == i18n.Chinese {
191+
return "用法:version"
192+
}
193+
return "Usage: version"
194+
}
195+
196+
func versionFlagErrorText() string {
197+
if i18n.CurrentLanguage() == i18n.Chinese {
198+
return "--version 只能单独使用,或与 --output 一起使用"
199+
}
200+
return "--version can only be used by itself or with --output"
201+
}

0 commit comments

Comments
 (0)