refactor: fix contextcheck lint errors on magefile by passing mage context
This commit is contained in:
parent
cea8c7807d
commit
0a1104b75c
222
magefile.go
222
magefile.go
|
|
@ -87,8 +87,8 @@ func goDetectVerboseFlag() string {
|
||||||
return fmt.Sprintf("-v=%t", mg.Verbose())
|
return fmt.Sprintf("-v=%t", mg.Verbose())
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGitCommandWithOutput(arg ...string) (output []byte, err error) {
|
func runGitCommandWithOutput(ctx context.Context, arg ...string) (output []byte, err error) {
|
||||||
cmd := exec.Command("git", arg...)
|
cmd := exec.CommandContext(ctx, "git", arg...)
|
||||||
output, err = cmd.Output()
|
output, err = cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var ee *exec.ExitError
|
var ee *exec.ExitError
|
||||||
|
|
@ -101,8 +101,8 @@ func runGitCommandWithOutput(arg ...string) (output []byte, err error) {
|
||||||
return output, nil
|
return output, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRawVersionString() (version string, err error) {
|
func getRawVersionString(ctx context.Context) (version string, err error) {
|
||||||
version, err = getRawVersionNumber()
|
version, err = getRawVersionNumber(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +118,7 @@ func getRawVersionString() (version string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRawVersionNumber() (version string, err error) {
|
func getRawVersionNumber(ctx context.Context) (version string, err error) {
|
||||||
versionEnv := os.Getenv("RELEASE_VERSION")
|
versionEnv := os.Getenv("RELEASE_VERSION")
|
||||||
if versionEnv != "" {
|
if versionEnv != "" {
|
||||||
return versionEnv, nil
|
return versionEnv, nil
|
||||||
|
|
@ -132,19 +132,19 @@ func getRawVersionNumber() (version string, err error) {
|
||||||
return strings.Replace(os.Getenv("DRONE_BRANCH"), "release/v", "", 1), nil
|
return strings.Replace(os.Getenv("DRONE_BRANCH"), "release/v", "", 1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
versionBytes, err := runGitCommandWithOutput("describe", "--tags", "--always", "--abbrev=10")
|
versionBytes, err := runGitCommandWithOutput(ctx, "describe", "--tags", "--always", "--abbrev=10")
|
||||||
return string(versionBytes), err
|
return string(versionBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func setVersion() error {
|
func setVersion(ctx context.Context) error {
|
||||||
versionNumber, err := getRawVersionNumber()
|
versionNumber, err := getRawVersionNumber(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
VersionNumber = strings.Trim(versionNumber, "\n")
|
VersionNumber = strings.Trim(versionNumber, "\n")
|
||||||
VersionNumber = strings.Replace(VersionNumber, "-g", "-", 1)
|
VersionNumber = strings.Replace(VersionNumber, "-g", "-", 1)
|
||||||
|
|
||||||
version, err := getRawVersionString()
|
version, err := getRawVersionString(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting version: %w", err)
|
return fmt.Errorf("error getting version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -178,13 +178,13 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some variables have external dependencies (like git) which may not always be available.
|
// Some variables have external dependencies (like git) which may not always be available.
|
||||||
func initVars() error {
|
func initVars(ctx context.Context) error {
|
||||||
// Always include osusergo to use pure Go os/user implementation instead of CGO.
|
// Always include osusergo to use pure Go os/user implementation instead of CGO.
|
||||||
// This prevents SIGFPE crashes when running under systemd without HOME set,
|
// This prevents SIGFPE crashes when running under systemd without HOME set,
|
||||||
// caused by glibc's getpwuid_r() failing in certain environments.
|
// caused by glibc's getpwuid_r() failing in certain environments.
|
||||||
// See: https://github.com/go-vikunja/vikunja/issues/2170
|
// See: https://github.com/go-vikunja/vikunja/issues/2170
|
||||||
Tags = "osusergo " + strings.ReplaceAll(os.Getenv("TAGS"), ",", " ")
|
Tags = "osusergo " + strings.ReplaceAll(os.Getenv("TAGS"), ",", " ")
|
||||||
if err := setVersion(); err != nil {
|
if err := setVersion(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
setBinLocation()
|
setBinLocation()
|
||||||
|
|
@ -193,8 +193,8 @@ func initVars() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAndStreamOutput(cmd string, args ...string) error {
|
func runAndStreamOutput(ctx context.Context, cmd string, args ...string) error {
|
||||||
c := exec.Command(cmd, args...)
|
c := exec.CommandContext(ctx, cmd, args...)
|
||||||
|
|
||||||
c.Env = os.Environ()
|
c.Env = os.Environ()
|
||||||
c.Stdout = os.Stdout
|
c.Stdout = os.Stdout
|
||||||
|
|
@ -206,10 +206,10 @@ func runAndStreamOutput(cmd string, args ...string) error {
|
||||||
|
|
||||||
// Will check if the tool exists and if not install it from the provided import path
|
// Will check if the tool exists and if not install it from the provided import path
|
||||||
// If any errors occur, it will exit with a status code of 1.
|
// If any errors occur, it will exit with a status code of 1.
|
||||||
func checkAndInstallGoTool(tool, importPath string) error {
|
func checkAndInstallGoTool(ctx context.Context, tool, importPath string) error {
|
||||||
if err := exec.Command(tool).Run(); err != nil && strings.Contains(err.Error(), "executable file not found") {
|
if err := exec.CommandContext(ctx, tool).Run(); err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||||
fmt.Printf("%s not installed, installing %s...\n", tool, importPath)
|
fmt.Printf("%s not installed, installing %s...\n", tool, importPath)
|
||||||
if err := exec.Command("go", "install", goDetectVerboseFlag(), importPath).Run(); err != nil { //nolint:gosec // Every caller to checkAndInstallGoTool is hard-coded at time of writing, so no injection possible.
|
if err := exec.CommandContext(ctx, "go", "install", goDetectVerboseFlag(), importPath).Run(); err != nil { //nolint:gosec // Every caller to checkAndInstallGoTool is hard-coded at time of writing, so no injection possible.
|
||||||
return fmt.Errorf("error installing %s: %w", tool, err)
|
return fmt.Errorf("error installing %s: %w", tool, err)
|
||||||
}
|
}
|
||||||
fmt.Println("Installed.")
|
fmt.Println("Installed.")
|
||||||
|
|
@ -324,16 +324,16 @@ func printSuccess(text string, args ...any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getE2EPort returns the port from the given env var, or a random available port.
|
// getE2EPort returns the port from the given env var, or a random available port.
|
||||||
func getE2EPort(envVar string) (int, error) {
|
func getE2EPort(ctx context.Context, envVar string) (int, error) {
|
||||||
if v := os.Getenv(envVar); v != "" {
|
if v := os.Getenv(envVar); v != "" {
|
||||||
return strconv.Atoi(v)
|
return strconv.Atoi(v)
|
||||||
}
|
}
|
||||||
return getRandomPort()
|
return getRandomPort(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRandomPort finds a random available TCP port.
|
// getRandomPort finds a random available TCP port.
|
||||||
func getRandomPort() (int, error) {
|
func getRandomPort(ctx context.Context) (int, error) {
|
||||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
l, err := (&net.ListenConfig{}).Listen(ctx, "tcp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -362,11 +362,15 @@ func killProcessGroup(cmd *exec.Cmd) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForHTTP polls a URL until it returns a 200 status or the timeout expires.
|
// waitForHTTP polls a URL until it returns a 200 status or the timeout expires.
|
||||||
func waitForHTTP(url string, timeout time.Duration) error {
|
func waitForHTTP(ctx context.Context, url string, timeout time.Duration) error {
|
||||||
deadline := time.Now().Add(timeout)
|
deadline := time.Now().Add(timeout)
|
||||||
client := &http.Client{Timeout: 2 * time.Second}
|
client := &http.Client{Timeout: 2 * time.Second}
|
||||||
for time.Now().Before(deadline) {
|
for time.Now().Before(deadline) {
|
||||||
resp, err := client.Get(url)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := client.Do(req)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
if resp.StatusCode == http.StatusOK {
|
if resp.StatusCode == http.StatusOK {
|
||||||
|
|
@ -379,7 +383,7 @@ func waitForHTTP(url string, timeout time.Duration) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fmt formats the code using go fmt
|
// Fmt formats the code using go fmt
|
||||||
func Fmt() error {
|
func Fmt(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
var goFiles []string
|
var goFiles []string
|
||||||
err := filepath.Walk(".", func(path string, info fs.FileInfo, err error) error {
|
err := filepath.Walk(".", func(path string, info fs.FileInfo, err error) error {
|
||||||
|
|
@ -395,37 +399,37 @@ func Fmt() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
args := append([]string{"-s", "-w"}, goFiles...)
|
args := append([]string{"-s", "-w"}, goFiles...)
|
||||||
return runAndStreamOutput("gofmt", args...)
|
return runAndStreamOutput(ctx, "gofmt", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Test mg.Namespace
|
type Test mg.Namespace
|
||||||
|
|
||||||
// Feature runs the feature tests
|
// Feature runs the feature tests
|
||||||
func (Test) Feature() error {
|
func (Test) Feature(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
||||||
return runAndStreamOutput("go", "test", goDetectVerboseFlag(), "-p", "1", "-coverprofile", "cover.out", "-timeout", "45m", "-short", "./...")
|
return runAndStreamOutput(ctx, "go", "test", goDetectVerboseFlag(), "-p", "1", "-coverprofile", "cover.out", "-timeout", "45m", "-short", "./...")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coverage runs the tests and builds the coverage html file from coverage output
|
// Coverage runs the tests and builds the coverage html file from coverage output
|
||||||
func (Test) Coverage() error {
|
func (Test) Coverage(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
mg.Deps(Test.Feature)
|
mg.Deps(Test.Feature)
|
||||||
return runAndStreamOutput("go", "tool", "cover", "-html=cover.out", "-o", "cover.html")
|
return runAndStreamOutput(ctx, "go", "tool", "cover", "-html=cover.out", "-o", "cover.html")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Web runs the web tests
|
// Web runs the web tests
|
||||||
func (Test) Web() error {
|
func (Test) Web(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
||||||
args := []string{"test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "./pkg/webtests"}
|
args := []string{"test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "./pkg/webtests"}
|
||||||
return runAndStreamOutput("go", args...)
|
return runAndStreamOutput(ctx, "go", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Test) Filter(filter string) error {
|
func (Test) Filter(ctx context.Context, filter string) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
// We run everything sequentially and not in parallel to prevent issues with real test databases
|
||||||
return runAndStreamOutput("go", "test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "-run", filter, "-short", "./...")
|
return runAndStreamOutput(ctx, "go", "test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "-run", filter, "-short", "./...")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Test) All() {
|
func (Test) All() {
|
||||||
|
|
@ -436,9 +440,9 @@ func (Test) All() {
|
||||||
// E2EApi runs the end-to-end API tests in pkg/e2etests.
|
// E2EApi runs the end-to-end API tests in pkg/e2etests.
|
||||||
// These tests use the real event system (not events.Fake()) to verify
|
// These tests use the real event system (not events.Fake()) to verify
|
||||||
// the full async pipeline: web handler → DB → event dispatch → watermill → listener.
|
// the full async pipeline: web handler → DB → event dispatch → watermill → listener.
|
||||||
func (Test) E2EApi() error {
|
func (Test) E2EApi(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
return runAndStreamOutput("go", "test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "./pkg/e2etests")
|
return runAndStreamOutput(ctx, "go", "test", goDetectVerboseFlag(), "-p", "1", "-timeout", "45m", "./pkg/e2etests")
|
||||||
}
|
}
|
||||||
|
|
||||||
// E2E builds the API, starts it with an in-memory database and the frontend dev server,
|
// E2E builds the API, starts it with an in-memory database and the frontend dev server,
|
||||||
|
|
@ -458,15 +462,15 @@ func (Test) E2EApi() error {
|
||||||
// - VIKUNJA_E2E_FRONTEND_PORT: Frontend port (default: random)
|
// - VIKUNJA_E2E_FRONTEND_PORT: Frontend port (default: random)
|
||||||
// - VIKUNJA_E2E_TESTING_TOKEN: Testing token for seed endpoints (default: random)
|
// - VIKUNJA_E2E_TESTING_TOKEN: Testing token for seed endpoints (default: random)
|
||||||
// - VIKUNJA_E2E_SKIP_BUILD: Set to "true" to skip rebuilding the API binary (default: false)
|
// - VIKUNJA_E2E_SKIP_BUILD: Set to "true" to skip rebuilding the API binary (default: false)
|
||||||
func (Test) E2E(args string) error {
|
func (Test) E2E(ctx context.Context, args string) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
|
|
||||||
// Determine ports
|
// Determine ports
|
||||||
apiPort, err := getE2EPort("VIKUNJA_E2E_API_PORT")
|
apiPort, err := getE2EPort(ctx, "VIKUNJA_E2E_API_PORT")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get API port: %w", err)
|
return fmt.Errorf("could not get API port: %w", err)
|
||||||
}
|
}
|
||||||
frontendPort, err := getE2EPort("VIKUNJA_E2E_FRONTEND_PORT")
|
frontendPort, err := getE2EPort(ctx, "VIKUNJA_E2E_FRONTEND_PORT")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get frontend port: %w", err)
|
return fmt.Errorf("could not get frontend port: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -485,7 +489,7 @@ func (Test) E2E(args string) error {
|
||||||
// Build the API binary (unless skipped)
|
// Build the API binary (unless skipped)
|
||||||
if os.Getenv("VIKUNJA_E2E_SKIP_BUILD") != "true" {
|
if os.Getenv("VIKUNJA_E2E_SKIP_BUILD") != "true" {
|
||||||
fmt.Println("\n--- Building API binary ---")
|
fmt.Println("\n--- Building API binary ---")
|
||||||
if err := (Build{}).Build(); err != nil {
|
if err := (Build{}).Build(ctx); err != nil {
|
||||||
return fmt.Errorf("failed to build API: %w", err)
|
return fmt.Errorf("failed to build API: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -507,7 +511,7 @@ func (Test) E2E(args string) error {
|
||||||
// Start the API server — all config via env vars, no config file
|
// Start the API server — all config via env vars, no config file
|
||||||
// Uses in-memory SQLite (no DB file on disk)
|
// Uses in-memory SQLite (no DB file on disk)
|
||||||
fmt.Println("\n--- Starting API server ---")
|
fmt.Println("\n--- Starting API server ---")
|
||||||
apiCmd := exec.Command("./vikunja", "web")
|
apiCmd := exec.CommandContext(ctx, "./vikunja", "web")
|
||||||
apiCmd.Env = append(os.Environ(),
|
apiCmd.Env = append(os.Environ(),
|
||||||
fmt.Sprintf("VIKUNJA_SERVICE_INTERFACE=:%d", apiPort),
|
fmt.Sprintf("VIKUNJA_SERVICE_INTERFACE=:%d", apiPort),
|
||||||
fmt.Sprintf("VIKUNJA_SERVICE_PUBLICURL=http://127.0.0.1:%d/", apiPort),
|
fmt.Sprintf("VIKUNJA_SERVICE_PUBLICURL=http://127.0.0.1:%d/", apiPort),
|
||||||
|
|
@ -538,14 +542,14 @@ func (Test) E2E(args string) error {
|
||||||
// Wait for API to be ready
|
// Wait for API to be ready
|
||||||
apiBase := fmt.Sprintf("http://127.0.0.1:%d/api/v1", apiPort)
|
apiBase := fmt.Sprintf("http://127.0.0.1:%d/api/v1", apiPort)
|
||||||
fmt.Printf("Waiting for API at %s ...\n", apiBase)
|
fmt.Printf("Waiting for API at %s ...\n", apiBase)
|
||||||
if err := waitForHTTP(apiBase+"/info", 30*time.Second); err != nil {
|
if err := waitForHTTP(ctx, apiBase+"/info", 30*time.Second); err != nil {
|
||||||
return fmt.Errorf("API failed to start: %w", err)
|
return fmt.Errorf("API failed to start: %w", err)
|
||||||
}
|
}
|
||||||
printSuccess("API is ready!")
|
printSuccess("API is ready!")
|
||||||
|
|
||||||
// Build the frontend
|
// Build the frontend
|
||||||
fmt.Println("\n--- Building frontend ---")
|
fmt.Println("\n--- Building frontend ---")
|
||||||
buildFrontendCmd := exec.Command("pnpm", "build:dev")
|
buildFrontendCmd := exec.CommandContext(ctx, "pnpm", "build:dev")
|
||||||
buildFrontendCmd.Dir = "frontend"
|
buildFrontendCmd.Dir = "frontend"
|
||||||
buildFrontendCmd.Stdout = os.Stdout
|
buildFrontendCmd.Stdout = os.Stdout
|
||||||
buildFrontendCmd.Stderr = os.Stderr
|
buildFrontendCmd.Stderr = os.Stderr
|
||||||
|
|
@ -556,7 +560,7 @@ func (Test) E2E(args string) error {
|
||||||
|
|
||||||
// Serve the built frontend with vite preview (static, no file watchers)
|
// Serve the built frontend with vite preview (static, no file watchers)
|
||||||
fmt.Println("\n--- Starting frontend preview server ---")
|
fmt.Println("\n--- Starting frontend preview server ---")
|
||||||
frontendCmd := exec.Command("pnpm", "preview:dev", "--port", strconv.Itoa(frontendPort)) //nolint:gosec // This mage task runs end to end tests with environment-based configuration, it must use the port environment variable to suit its current environment.
|
frontendCmd := exec.CommandContext(ctx, "pnpm", "preview:dev", "--port", strconv.Itoa(frontendPort)) //nolint:gosec // This mage task runs end to end tests with environment-based configuration, it must use the port environment variable to suit its current environment.
|
||||||
frontendCmd.Dir = "frontend"
|
frontendCmd.Dir = "frontend"
|
||||||
frontendCmd.Stdout = os.Stdout
|
frontendCmd.Stdout = os.Stdout
|
||||||
frontendCmd.Stderr = os.Stderr
|
frontendCmd.Stderr = os.Stderr
|
||||||
|
|
@ -574,7 +578,7 @@ func (Test) E2E(args string) error {
|
||||||
// Wait for frontend to be ready
|
// Wait for frontend to be ready
|
||||||
frontendBase := fmt.Sprintf("http://127.0.0.1:%d", frontendPort)
|
frontendBase := fmt.Sprintf("http://127.0.0.1:%d", frontendPort)
|
||||||
fmt.Printf("Waiting for frontend at %s ...\n", frontendBase)
|
fmt.Printf("Waiting for frontend at %s ...\n", frontendBase)
|
||||||
if err := waitForHTTP(frontendBase, 60*time.Second); err != nil {
|
if err := waitForHTTP(ctx, frontendBase, 60*time.Second); err != nil {
|
||||||
return fmt.Errorf("frontend failed to start: %w", err)
|
return fmt.Errorf("frontend failed to start: %w", err)
|
||||||
}
|
}
|
||||||
printSuccess("Frontend is ready!")
|
printSuccess("Frontend is ready!")
|
||||||
|
|
@ -585,7 +589,7 @@ func (Test) E2E(args string) error {
|
||||||
if strings.TrimSpace(args) != "" {
|
if strings.TrimSpace(args) != "" {
|
||||||
playwrightArgs = append(playwrightArgs, strings.Fields(args)...)
|
playwrightArgs = append(playwrightArgs, strings.Fields(args)...)
|
||||||
}
|
}
|
||||||
playwrightCmd := exec.Command("pnpm", playwrightArgs...)
|
playwrightCmd := exec.CommandContext(ctx, "pnpm", playwrightArgs...)
|
||||||
playwrightCmd.Dir = "frontend"
|
playwrightCmd.Dir = "frontend"
|
||||||
playwrightCmd.Env = append(os.Environ(),
|
playwrightCmd.Env = append(os.Environ(),
|
||||||
fmt.Sprintf("API_URL=%s/", apiBase),
|
fmt.Sprintf("API_URL=%s/", apiBase),
|
||||||
|
|
@ -609,7 +613,7 @@ func (Test) E2E(args string) error {
|
||||||
type Check mg.Namespace
|
type Check mg.Namespace
|
||||||
|
|
||||||
// GotSwag checks if the swagger docs need to be re-generated from the code annotations
|
// GotSwag checks if the swagger docs need to be re-generated from the code annotations
|
||||||
func (Check) GotSwag() error {
|
func (Check) GotSwag(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
// The check is pretty cheaply done: We take the hash of the swagger.json file, generate the docs,
|
// The check is pretty cheaply done: We take the hash of the swagger.json file, generate the docs,
|
||||||
// hash the file again and compare the two hashes to see if anything changed. If that's the case,
|
// hash the file again and compare the two hashes to see if anything changed. If that's the case,
|
||||||
|
|
@ -622,7 +626,7 @@ func (Check) GotSwag() error {
|
||||||
return fmt.Errorf("error getting old hash of the swagger docs: %w", err)
|
return fmt.Errorf("error getting old hash of the swagger docs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if generateErr := (Generate{}).SwaggerDocs(); generateErr != nil {
|
if generateErr := (Generate{}).SwaggerDocs(ctx); generateErr != nil {
|
||||||
return generateErr
|
return generateErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -793,26 +797,26 @@ func extractTranslationKeysFromFile(filePath string) ([]TranslationKey, error) {
|
||||||
return keys, nil
|
return keys, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkGolangCiLintInstalled() error {
|
func checkGolangCiLintInstalled(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
if err := exec.Command("golangci-lint").Run(); err != nil && strings.Contains(err.Error(), "executable file not found") {
|
if err := exec.CommandContext(ctx, "golangci-lint").Run(); err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||||
return fmt.Errorf("golangci-lint executable failed to run, please manually install golangci-lint by running the command: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.4.0")
|
return fmt.Errorf("golangci-lint executable failed to run, please manually install golangci-lint by running the command: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.4.0")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Check) Golangci() error {
|
func (Check) Golangci(ctx context.Context) error {
|
||||||
if err := checkGolangCiLintInstalled(); err != nil {
|
if err := checkGolangCiLintInstalled(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return runAndStreamOutput("golangci-lint", "run")
|
return runAndStreamOutput(ctx, "golangci-lint", "run")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Check) GolangciFix() error {
|
func (Check) GolangciFix(ctx context.Context) error {
|
||||||
if err := checkGolangCiLintInstalled(); err != nil {
|
if err := checkGolangCiLintInstalled(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return runAndStreamOutput("golangci-lint", "run", "--fix")
|
return runAndStreamOutput(ctx, "golangci-lint", "run", "--fix")
|
||||||
}
|
}
|
||||||
|
|
||||||
// All runs golangci and the swagger test in parallel
|
// All runs golangci and the swagger test in parallel
|
||||||
|
|
@ -828,9 +832,9 @@ func (Check) All() {
|
||||||
type Build mg.Namespace
|
type Build mg.Namespace
|
||||||
|
|
||||||
// Clean cleans all build, executable and bindata files
|
// Clean cleans all build, executable and bindata files
|
||||||
func (Build) Clean() error {
|
func (Build) Clean(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
if err := exec.Command("go", "clean", "./...").Run(); err != nil {
|
if err := exec.CommandContext(ctx, "go", "clean", "./...").Run(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.Remove(Executable); err != nil && !os.IsNotExist(err) {
|
if err := os.Remove(Executable); err != nil && !os.IsNotExist(err) {
|
||||||
|
|
@ -846,7 +850,7 @@ func (Build) Clean() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a vikunja binary, ready to run
|
// Build builds a vikunja binary, ready to run
|
||||||
func (Build) Build() error {
|
func (Build) Build(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
// Check if the frontend dist folder exists
|
// Check if the frontend dist folder exists
|
||||||
distPath := filepath.Join("frontend", "dist")
|
distPath := filepath.Join("frontend", "dist")
|
||||||
|
|
@ -866,7 +870,7 @@ func (Build) Build() error {
|
||||||
fmt.Printf("Warning: %s not found, created empty file\n", indexFile)
|
fmt.Printf("Warning: %s not found, created empty file\n", indexFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runAndStreamOutput("go", "build", goDetectVerboseFlag(), "-tags", Tags, "-ldflags", "-s -w "+Ldflags, "-o", Executable)
|
return runAndStreamOutput(ctx, "go", "build", goDetectVerboseFlag(), "-tags", Tags, "-ldflags", "-s -w "+Ldflags, "-o", Executable)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Build) SaveVersionToFile() error {
|
func (Build) SaveVersionToFile() error {
|
||||||
|
|
@ -898,9 +902,9 @@ func (Release) Release(ctx context.Context) error {
|
||||||
|
|
||||||
// Run compiling in parallel to speed it up
|
// Run compiling in parallel to speed it up
|
||||||
errs, _ := errgroup.WithContext(ctx)
|
errs, _ := errgroup.WithContext(ctx)
|
||||||
errs.Go((Release{}).Windows)
|
errgroupGoWithContext(ctx, errs, (Release{}).Windows)
|
||||||
errs.Go((Release{}).Linux)
|
errgroupGoWithContext(ctx, errs, (Release{}).Linux)
|
||||||
errs.Go((Release{}).Darwin)
|
errgroupGoWithContext(ctx, errs, (Release{}).Darwin)
|
||||||
if err := errs.Wait(); err != nil {
|
if err := errs.Wait(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -917,13 +921,19 @@ func (Release) Release(ctx context.Context) error {
|
||||||
if err := (Release{}).OsPackage(); err != nil {
|
if err := (Release{}).OsPackage(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := (Release{}).Zip(); err != nil {
|
if err := (Release{}).Zip(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func errgroupGoWithContext(ctx context.Context, errs *errgroup.Group, do func(context.Context) error) {
|
||||||
|
errs.Go(func() error {
|
||||||
|
return do(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Dirs creates all directories needed to release vikunja
|
// Dirs creates all directories needed to release vikunja
|
||||||
func (Release) Dirs() error {
|
func (Release) Dirs() error {
|
||||||
for _, d := range []string{"binaries", "release", "zip"} {
|
for _, d := range []string{"binaries", "release", "zip"} {
|
||||||
|
|
@ -934,19 +944,19 @@ func (Release) Dirs() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareXgo() error {
|
func prepareXgo(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
if err := checkAndInstallGoTool("xgo", "src.techknowlogick.com/xgo"); err != nil {
|
if err := checkAndInstallGoTool(ctx, "xgo", "src.techknowlogick.com/xgo"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Pulling latest xgo docker image...")
|
fmt.Println("Pulling latest xgo docker image...")
|
||||||
return runAndStreamOutput("docker", "pull", "ghcr.io/techknowlogick/xgo:latest")
|
return runAndStreamOutput(ctx, "docker", "pull", "ghcr.io/techknowlogick/xgo:latest")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runXgo(targets string) error {
|
func runXgo(ctx context.Context, targets string) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
if err := checkAndInstallGoTool("xgo", "src.techknowlogick.com/xgo"); err != nil {
|
if err := checkAndInstallGoTool(ctx, "xgo", "src.techknowlogick.com/xgo"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -961,7 +971,7 @@ func runXgo(targets string) error {
|
||||||
outName = Executable + "-" + Version
|
outName = Executable + "-" + Version
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runAndStreamOutput("xgo",
|
if err := runAndStreamOutput(ctx, "xgo",
|
||||||
"-dest", "./"+DIST+"/binaries",
|
"-dest", "./"+DIST+"/binaries",
|
||||||
"-tags", "netgo "+Tags,
|
"-tags", "netgo "+Tags,
|
||||||
"-ldflags", extraLdflags+Ldflags,
|
"-ldflags", extraLdflags+Ldflags,
|
||||||
|
|
@ -987,12 +997,12 @@ func runXgo(targets string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows builds binaries for windows
|
// Windows builds binaries for windows
|
||||||
func (Release) Windows() error {
|
func (Release) Windows(ctx context.Context) error {
|
||||||
return runXgo("windows/*")
|
return runXgo(ctx, "windows/*")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linux builds binaries for linux
|
// Linux builds binaries for linux
|
||||||
func (Release) Linux() error {
|
func (Release) Linux(ctx context.Context) error {
|
||||||
targets := []string{
|
targets := []string{
|
||||||
"linux/amd64",
|
"linux/amd64",
|
||||||
"linux/arm-5",
|
"linux/arm-5",
|
||||||
|
|
@ -1005,15 +1015,15 @@ func (Release) Linux() error {
|
||||||
"linux/mips64le",
|
"linux/mips64le",
|
||||||
"linux/riscv64",
|
"linux/riscv64",
|
||||||
}
|
}
|
||||||
return runXgo(strings.Join(targets, ","))
|
return runXgo(ctx, strings.Join(targets, ","))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Darwin builds binaries for darwin
|
// Darwin builds binaries for darwin
|
||||||
func (Release) Darwin() error {
|
func (Release) Darwin(ctx context.Context) error {
|
||||||
return runXgo("darwin-10.15/*")
|
return runXgo(ctx, "darwin-10.15/*")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Release) Xgo(target string) error {
|
func (Release) Xgo(ctx context.Context, target string) error {
|
||||||
parts := strings.Split(target, "/")
|
parts := strings.Split(target, "/")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
return fmt.Errorf("invalid target")
|
return fmt.Errorf("invalid target")
|
||||||
|
|
@ -1024,7 +1034,7 @@ func (Release) Xgo(target string) error {
|
||||||
variant = "-" + strings.ReplaceAll(parts[2], "v", "")
|
variant = "-" + strings.ReplaceAll(parts[2], "v", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
return runXgo(parts[0] + "/" + parts[1] + variant)
|
return runXgo(ctx, parts[0]+"/"+parts[1]+variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compress compresses the built binaries in dist/binaries/ to reduce their filesize
|
// Compress compresses the built binaries in dist/binaries/ to reduce their filesize
|
||||||
|
|
@ -1052,10 +1062,10 @@ func (Release) Compress(ctx context.Context) error {
|
||||||
|
|
||||||
// Runs compressing in parallel since upx is single-threaded
|
// Runs compressing in parallel since upx is single-threaded
|
||||||
errs.Go(func() error {
|
errs.Go(func() error {
|
||||||
if err := runAndStreamOutput("chmod", "+x", path); err != nil { // Make sure all binaries are executable. Sometimes the CI does weird things and they're not.
|
if err := runAndStreamOutput(ctx, "chmod", "+x", path); err != nil { // Make sure all binaries are executable. Sometimes the CI does weird things and they're not.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return runAndStreamOutput("upx", "-9", path)
|
return runAndStreamOutput(ctx, "upx", "-9", path)
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -1155,7 +1165,7 @@ func (Release) OsPackage() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zip creates a zip file from all os-package folders in dist/release
|
// Zip creates a zip file from all os-package folders in dist/release
|
||||||
func (Release) Zip() error {
|
func (Release) Zip(ctx context.Context) error {
|
||||||
rootDir, err := os.Getwd()
|
rootDir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get working directory: %w", err)
|
return fmt.Errorf("could not get working directory: %w", err)
|
||||||
|
|
@ -1173,7 +1183,7 @@ func (Release) Zip() error {
|
||||||
fmt.Printf("Zipping %s...\n", info.Name())
|
fmt.Printf("Zipping %s...\n", info.Name())
|
||||||
|
|
||||||
zipFile := filepath.Join(rootDir, DIST, "zip", info.Name()+".zip")
|
zipFile := filepath.Join(rootDir, DIST, "zip", info.Name()+".zip")
|
||||||
c := exec.Command("zip", "-r", zipFile, ".", "-i", "*") //nolint:gosec // This mage task creates zips of every directory recursively, it must use the directory name in the resulting file path to distinguish output files.
|
c := exec.CommandContext(ctx, "zip", "-r", zipFile, ".", "-i", "*") //nolint:gosec // This mage task creates zips of every directory recursively, it must use the directory name in the resulting file path to distinguish output files.
|
||||||
c.Dir = path
|
c.Dir = path
|
||||||
out, err := c.Output()
|
out, err := c.Output()
|
||||||
fmt.Print(string(out))
|
fmt.Print(string(out))
|
||||||
|
|
@ -1186,9 +1196,9 @@ func (Release) Zip() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reprepro creates a debian repo structure
|
// Reprepro creates a debian repo structure
|
||||||
func (Release) Reprepro() error {
|
func (Release) Reprepro(ctx context.Context) error {
|
||||||
mg.Deps(setVersion, setBinLocation)
|
mg.Deps(setVersion, setBinLocation)
|
||||||
return runAndStreamOutput("reprepro_expect", "debian", "includedeb", "buster", "./"+DIST+"/os-packages/"+Executable+"_"+strings.ReplaceAll(VersionNumber, "v0", "0")+"_amd64.deb")
|
return runAndStreamOutput(ctx, "reprepro_expect", "debian", "includedeb", "buster", "./"+DIST+"/os-packages/"+Executable+"_"+strings.ReplaceAll(VersionNumber, "v0", "0")+"_amd64.deb")
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareNFPMConfig prepares the nfpm config
|
// PrepareNFPMConfig prepares the nfpm config
|
||||||
|
|
@ -1215,7 +1225,7 @@ func (Release) PrepareNFPMConfig() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Packages creates deb, rpm and apk packages
|
// Packages creates deb, rpm and apk packages
|
||||||
func (Release) Packages() error {
|
func (Release) Packages(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -1223,10 +1233,10 @@ func (Release) Packages() error {
|
||||||
if binpath == "" {
|
if binpath == "" {
|
||||||
binpath = "nfpm"
|
binpath = "nfpm"
|
||||||
}
|
}
|
||||||
err = exec.Command(binpath).Run()
|
err = exec.CommandContext(ctx, binpath).Run()
|
||||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||||
binpath = "/usr/bin/nfpm"
|
binpath = "/usr/bin/nfpm"
|
||||||
err = exec.Command(binpath).Run()
|
err = exec.CommandContext(ctx, binpath).Run()
|
||||||
}
|
}
|
||||||
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
if err != nil && strings.Contains(err.Error(), "executable file not found") {
|
||||||
return fmt.Errorf("executable %s not found: please manually install nfpm by running the command: curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b $(go env GOPATH)/bin", binpath)
|
return fmt.Errorf("executable %s not found: please manually install nfpm by running the command: curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b $(go env GOPATH)/bin", binpath)
|
||||||
|
|
@ -1242,13 +1252,13 @@ func (Release) Packages() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := runAndStreamOutput(binpath, "pkg", "--packager", "deb", "--target", releasePath); err != nil {
|
if err := runAndStreamOutput(ctx, binpath, "pkg", "--packager", "deb", "--target", releasePath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := runAndStreamOutput(binpath, "pkg", "--packager", "rpm", "--target", releasePath); err != nil {
|
if err := runAndStreamOutput(ctx, binpath, "pkg", "--packager", "rpm", "--target", releasePath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := runAndStreamOutput(binpath, "pkg", "--packager", "apk", "--target", releasePath); err != nil {
|
if err := runAndStreamOutput(ctx, binpath, "pkg", "--packager", "apk", "--target", releasePath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1493,13 +1503,13 @@ type Generate mg.Namespace
|
||||||
const DefaultConfigYAMLSamplePath = "config.yml.sample"
|
const DefaultConfigYAMLSamplePath = "config.yml.sample"
|
||||||
|
|
||||||
// SwaggerDocs generates the swagger docs from the code annotations
|
// SwaggerDocs generates the swagger docs from the code annotations
|
||||||
func (Generate) SwaggerDocs() error {
|
func (Generate) SwaggerDocs(ctx context.Context) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
|
|
||||||
if err := checkAndInstallGoTool("swag", "github.com/swaggo/swag/cmd/swag"); err != nil {
|
if err := checkAndInstallGoTool(ctx, "swag", "github.com/swaggo/swag/cmd/swag"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return runAndStreamOutput("swag", "init", "-g", "./pkg/routes/routes.go", "--parseDependency", "-d", ".", "-o", "./pkg/swagger")
|
return runAndStreamOutput(ctx, "swag", "init", "-g", "./pkg/routes/routes.go", "--parseDependency", "-d", ".", "-o", "./pkg/swagger")
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigNode struct {
|
type ConfigNode struct {
|
||||||
|
|
@ -1636,7 +1646,7 @@ func (Generate) ConfigYAML(commented bool) {
|
||||||
// The second argument is a path to a plan file that will be copied to the new worktree (pass "" to skip).
|
// The second argument is a path to a plan file that will be copied to the new worktree (pass "" to skip).
|
||||||
// The worktree is created in the parent directory (../).
|
// The worktree is created in the parent directory (../).
|
||||||
// It also copies the current config.yml with an updated rootpath, and initializes the frontend.
|
// It also copies the current config.yml with an updated rootpath, and initializes the frontend.
|
||||||
func (Dev) PrepareWorktree(name string, planPath string) error {
|
func (Dev) PrepareWorktree(ctx context.Context, name string, planPath string) error {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return fmt.Errorf("name is required: mage dev:prepare-worktree <name> <plan-path>")
|
return fmt.Errorf("name is required: mage dev:prepare-worktree <name> <plan-path>")
|
||||||
}
|
}
|
||||||
|
|
@ -1647,7 +1657,7 @@ func (Dev) PrepareWorktree(name string, planPath string) error {
|
||||||
fmt.Printf("Creating worktree at %s with branch %s...\n", worktreePath, name)
|
fmt.Printf("Creating worktree at %s with branch %s...\n", worktreePath, name)
|
||||||
|
|
||||||
// Create the git worktree
|
// Create the git worktree
|
||||||
cmd := exec.Command("git", "worktree", "add", worktreePath, "-b", name)
|
cmd := exec.CommandContext(ctx, "git", "worktree", "add", worktreePath, "-b", name)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
|
|
@ -1728,7 +1738,7 @@ func (Dev) PrepareWorktree(name string, planPath string) error {
|
||||||
frontendDir := filepath.Join(worktreePath, "frontend")
|
frontendDir := filepath.Join(worktreePath, "frontend")
|
||||||
|
|
||||||
// Run pnpm install
|
// Run pnpm install
|
||||||
pnpmCmd := exec.Command("pnpm", "i")
|
pnpmCmd := exec.CommandContext(ctx, "pnpm", "i")
|
||||||
pnpmCmd.Dir = frontendDir
|
pnpmCmd.Dir = frontendDir
|
||||||
pnpmCmd.Stdout = os.Stdout
|
pnpmCmd.Stdout = os.Stdout
|
||||||
pnpmCmd.Stderr = os.Stderr
|
pnpmCmd.Stderr = os.Stderr
|
||||||
|
|
@ -1737,7 +1747,7 @@ func (Dev) PrepareWorktree(name string, planPath string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run patch-sass-embedded (shell alias from devenv)
|
// Run patch-sass-embedded (shell alias from devenv)
|
||||||
patchCmd := exec.Command("bash", "-ic", "patch-sass-embedded")
|
patchCmd := exec.CommandContext(ctx, "bash", "-ic", "patch-sass-embedded")
|
||||||
patchCmd.Dir = frontendDir
|
patchCmd.Dir = frontendDir
|
||||||
patchCmd.Stdout = os.Stdout
|
patchCmd.Stdout = os.Stdout
|
||||||
patchCmd.Stderr = os.Stderr
|
patchCmd.Stderr = os.Stderr
|
||||||
|
|
@ -1756,8 +1766,8 @@ func (Dev) PrepareWorktree(name string, planPath string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// printReleaseStats prints commit statistics for the range between two refs.
|
// printReleaseStats prints commit statistics for the range between two refs.
|
||||||
func printReleaseStats(fromRef, toRef string) error {
|
func printReleaseStats(ctx context.Context, fromRef, toRef string) error {
|
||||||
output, err := runGitCommandWithOutput("log", fromRef+".."+toRef, "--oneline")
|
output, err := runGitCommandWithOutput(ctx, "log", fromRef+".."+toRef, "--oneline")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get commit log: %w", err)
|
return fmt.Errorf("failed to get commit log: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1811,7 +1821,7 @@ func printReleaseStats(fromRef, toRef string) error {
|
||||||
// TagRelease creates a new release tag with changelog.
|
// TagRelease creates a new release tag with changelog.
|
||||||
// It updates the version badge in README.md, generates changelog using git-cliff,
|
// It updates the version badge in README.md, generates changelog using git-cliff,
|
||||||
// commits the changes, and creates an annotated tag.
|
// commits the changes, and creates an annotated tag.
|
||||||
func (Dev) TagRelease(version string) error {
|
func (Dev) TagRelease(ctx context.Context, version string) error {
|
||||||
if version == "" {
|
if version == "" {
|
||||||
return fmt.Errorf("version is required: mage dev:tag-release <version>")
|
return fmt.Errorf("version is required: mage dev:tag-release <version>")
|
||||||
}
|
}
|
||||||
|
|
@ -1824,7 +1834,7 @@ func (Dev) TagRelease(version string) error {
|
||||||
fmt.Printf("Creating release %s...\n", version)
|
fmt.Printf("Creating release %s...\n", version)
|
||||||
|
|
||||||
// Get the last tag
|
// Get the last tag
|
||||||
lastTagBytes, err := runGitCommandWithOutput("describe", "--tags", "--abbrev=0")
|
lastTagBytes, err := runGitCommandWithOutput(ctx, "describe", "--tags", "--abbrev=0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get last tag: %w", err)
|
return fmt.Errorf("failed to get last tag: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1832,13 +1842,13 @@ func (Dev) TagRelease(version string) error {
|
||||||
fmt.Printf("Last tag: %s\n", lastTag)
|
fmt.Printf("Last tag: %s\n", lastTag)
|
||||||
|
|
||||||
// Print commit statistics
|
// Print commit statistics
|
||||||
if err := printReleaseStats(lastTag, "HEAD"); err != nil {
|
if err := printReleaseStats(ctx, lastTag, "HEAD"); err != nil {
|
||||||
fmt.Printf("Warning: could not print release stats: %v\n", err)
|
fmt.Printf("Warning: could not print release stats: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate changelog using git cliff
|
// Generate changelog using git cliff
|
||||||
fmt.Println("Generating changelog...")
|
fmt.Println("Generating changelog...")
|
||||||
changelogBytes, err := runGitCommandWithOutput("cliff", lastTag+"..HEAD", "--tag", version)
|
changelogBytes, err := runGitCommandWithOutput(ctx, "cliff", lastTag+"..HEAD", "--tag", version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to generate changelog: %w", err)
|
return fmt.Errorf("failed to generate changelog: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1868,12 +1878,12 @@ func (Dev) TagRelease(version string) error {
|
||||||
// Commit the changes
|
// Commit the changes
|
||||||
fmt.Println("Committing changes...")
|
fmt.Println("Committing changes...")
|
||||||
commitMsg := fmt.Sprintf("chore: %s release preparations", version)
|
commitMsg := fmt.Sprintf("chore: %s release preparations", version)
|
||||||
cmd := exec.Command("git", "add", "README.md", "CHANGELOG.md", "frontend/package.json")
|
cmd := exec.CommandContext(ctx, "git", "add", "README.md", "CHANGELOG.md", "frontend/package.json")
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
return fmt.Errorf("failed to stage files: %w", err)
|
return fmt.Errorf("failed to stage files: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = exec.Command("git", "commit", "-m", commitMsg)
|
cmd = exec.CommandContext(ctx, "git", "commit", "-m", commitMsg)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
|
|
@ -1885,7 +1895,7 @@ func (Dev) TagRelease(version string) error {
|
||||||
|
|
||||||
// Create the annotated tag
|
// Create the annotated tag
|
||||||
fmt.Printf("Creating tag %s...\n", version)
|
fmt.Printf("Creating tag %s...\n", version)
|
||||||
cmd = exec.Command("git", "tag", "-a", version, "-m", tagMessage)
|
cmd = exec.CommandContext(ctx, "git", "tag", "-a", version, "-m", tagMessage)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
|
|
@ -2070,7 +2080,7 @@ func prepareTagMessage(changelog string) string {
|
||||||
type Plugins mg.Namespace
|
type Plugins mg.Namespace
|
||||||
|
|
||||||
// Build compiles a Go plugin at the provided path.
|
// Build compiles a Go plugin at the provided path.
|
||||||
func (Plugins) Build(pathToSourceFiles string) error {
|
func (Plugins) Build(ctx context.Context, pathToSourceFiles string) error {
|
||||||
mg.Deps(initVars)
|
mg.Deps(initVars)
|
||||||
if pathToSourceFiles == "" {
|
if pathToSourceFiles == "" {
|
||||||
return fmt.Errorf("please provide a plugin path")
|
return fmt.Errorf("please provide a plugin path")
|
||||||
|
|
@ -2086,5 +2096,5 @@ func (Plugins) Build(pathToSourceFiles string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
out := filepath.Join("plugins", filepath.Base(pathToSourceFiles)+".so")
|
out := filepath.Join("plugins", filepath.Base(pathToSourceFiles)+".so")
|
||||||
return runAndStreamOutput("go", "build", "-buildmode=plugin", "-tags", Tags, "-o", out, pathToSourceFiles)
|
return runAndStreamOutput(ctx, "go", "build", "-buildmode=plugin", "-tags", Tags, "-o", out, pathToSourceFiles)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue