Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
version: "2"
run:
tests: true
build-tags:
- stave
linters:
default: none
enable:
Expand Down Expand Up @@ -428,6 +430,10 @@ linters:
- linters:
- forbidigo
path: testmain_test\.go$
- linters:
- noctx
- unused
path: stavefile\.go$
paths:
- third_party$
- builtin$
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Detailed API reference documentation as well as an architecture overview for contributors.

- Pretty-printed debug logs, both in "outer" Stave execution _and_ in execution of compiled stavefile.

- `CHANGELOG.md`! (And first formally-versioned release of Stave.)

### Changed
Expand Down
1 change: 0 additions & 1 deletion cmd/stave/testdata/alias/stavefile.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
39 changes: 0 additions & 39 deletions install_test.go

This file was deleted.

3 changes: 3 additions & 0 deletions internal/parallelism/parallelism.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package parallelism

import (
"log/slog"
"os"
"runtime"
"strconv"
Expand Down Expand Up @@ -30,6 +31,8 @@ func Apply(envMap map[string]string) error {
numProcessors = getNumProcessors()
}

slog.Debug("setting parallelism-related env vars", slog.Int("num_processors", numProcessors))

newValStr := strconv.Itoa(numProcessors)

runtime.GOMAXPROCS(numProcessors)
Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/alias.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/command.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/func.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/importself/stavefile.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/repeating_synopsis.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
1 change: 0 additions & 1 deletion internal/parse/testdata/subcommands.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand Down
9 changes: 6 additions & 3 deletions pkg/sh/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import (
"errors"
"fmt"
"io"
"log/slog"
"log"
"os"
"os/exec"
"strings"

"github.com/yaklabco/stave/internal/dryrun"
"github.com/yaklabco/stave/internal/log"
"github.com/yaklabco/stave/pkg/st"
)

// simpleConsoleLogger is an unstructured logger designed for emitting simple
// messages to the console in `-v`/`--verbose` mode.
var simpleConsoleLogger = log.New(os.Stderr, "[STAVE] ", 0) //nolint:gochecknoglobals // This is unchanged in the course of the process lifecycle.

// RunCmd returns a function that will call Run with the given command. This is
// useful for creating command aliases to make your scripts easier to read, like
// this:
Expand Down Expand Up @@ -145,7 +148,7 @@ func run(env map[string]string, stdout, stderr io.Writer, cmd string, args ...st
}
// To protect against logging from doing exec in global variables
if st.Verbose() {
slog.Info("exec", slog.String(log.Cmd, cmd), slog.Any(log.Args, quoted))
simpleConsoleLogger.Println("exec:", cmd, strings.Join(quoted, " "))
}
err := theCmd.Run()

Expand Down
9 changes: 7 additions & 2 deletions pkg/st/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package st
import (
"context"
"fmt"
"log/slog"
"log"
"os"
"reflect"
"runtime"
"strings"
"sync"
)

// simpleConsoleLogger is an unstructured logger designed for emitting simple
// messages to the console in `-v`/`--verbose` mode.
var simpleConsoleLogger = log.New(os.Stderr, "[STAVE] ", 0) //nolint:gochecknoglobals // This is unchanged in the course of the process lifecycle.

type onceMap struct {
mu *sync.Mutex
m map[onceKey]*onceFun
Expand Down Expand Up @@ -208,7 +213,7 @@ type onceFun struct {
func (o *onceFun) run(ctx context.Context) error {
o.once.Do(func() {
if Verbose() {
slog.Info("running dependency", slog.String("dependency", displayName(o.fn.Name())))
simpleConsoleLogger.Println("Running dependency:", displayName(o.fn.Name()))
}
o.err = o.fn.Run(ctx)
})
Expand Down
15 changes: 4 additions & 11 deletions pkg/st/deps_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package st
import (
"bytes"
"fmt"
"log/slog"
"log"
"strings"
"testing"
)
Expand All @@ -12,16 +12,9 @@ func TestDepsLogging(t *testing.T) {
t.Setenv("STAVEFILE_VERBOSE", "1")
buf := &bytes.Buffer{}

defaultLogger := slog.Default()
logger := slog.New(slog.NewTextHandler(buf, &slog.HandlerOptions{
AddSource: false,
Level: nil,
ReplaceAttr: nil,
}))
slog.SetDefault(logger)
defer func() {
slog.SetDefault(defaultLogger)
}()
defaultLogger := simpleConsoleLogger
simpleConsoleLogger = log.New(buf, "", 0)
defer func() { simpleConsoleLogger = defaultLogger }()

foo()

Expand Down
28 changes: 16 additions & 12 deletions pkg/stave/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"go/build"
"go/parser"
"go/token"
"io"
Expand All @@ -31,6 +30,9 @@ import (
)

const (
charmbraceletLogMod = "github.com/charmbracelet/log"
staveMod = "github.com/yaklabco/stave"

testExeEnv = "STAVE_TEST_STRING"

hiExclam = "hi!"
Expand Down Expand Up @@ -949,8 +951,9 @@ func (t tLogWriter) Write(b []byte) (int, error) {
return len(b), nil
}

// Test if generated mainfile references anything other than the stdlib.
func TestOnlyStdLib(t *testing.T) {
// TestNoSelfDependencies checks that the generated `stave_output_file.go` code
// does not have dependencies on Stave itself.
func TestNoSelfDependencies(t *testing.T) {
t.Parallel()
testDataDir := "./testdata/onlyStdLib"
mu := mutexByDir(testDataDir)
Expand Down Expand Up @@ -992,13 +995,7 @@ func TestOnlyStdLib(t *testing.T) {
for _, importSpec := range fd.Imports {
// the path value comes in as a quoted string, i.e. literally \"context\"
path := strings.Trim(importSpec.Path.Value, "\"")
pkg, err := build.Default.Import(path, "./testdata/keep_flag", build.FindOnly)
require.NoError(t, err)

// Check if pkg.Dir is under GOROOT using filepath.Rel instead of deprecated filepath.HasPrefix
rel, err := filepath.Rel(build.Default.GOROOT, pkg.Dir)
require.NoError(t, err)
assert.False(t, strings.HasPrefix(rel, ".."))
assert.NotRegexp(t, "^"+staveMod, path)
}
}

Expand Down Expand Up @@ -1735,7 +1732,6 @@ func TestGoModules(t *testing.T) {

// beware, stave builds in go versions older than 1.17 so both build tag formats need to be present
err = os.WriteFile(filepath.Join(dir, "stavefile.go"), []byte(`//go:build stave
// +build stave

package main

Expand Down Expand Up @@ -1763,7 +1759,15 @@ func Test() {
cmd.Env = os.Environ()
cmd.Stderr = stderr
cmd.Stdout = stdout
require.NoError(t, cmd.Run(), "failed to run 'go mod init', stderr was: %s", stderr.String())
require.NoError(t, cmd.Run(), "failed to run 'go mod tidy', stderr was: %s", stderr.String())

// we need to run go mod tidy, since go build will no longer auto-add dependencies.
cmd = exec.Command("go", "get", charmbraceletLogMod)
cmd.Dir = dir
cmd.Env = os.Environ()
cmd.Stderr = stderr
cmd.Stdout = stdout
require.NoError(t, cmd.Run(), "failed to run 'go get %s', stderr was: %s", charmbraceletLogMod, stderr.String())

stderr.Reset()
stdout.Reset()
Expand Down
2 changes: 1 addition & 1 deletion pkg/stave/prettylog/prettylog.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func SetupPrettyLogger(writerForLogger io.Writer) *log.Logger {
logHandler := log.NewWithOptions(
writerForLogger,
log.Options{
Level: log.InfoLevel, // Setting this to lowest possible value, since slog will handle the actual filtering.
Level: log.InfoLevel, // This is the default; called can grab the returned logHandler and call the SetLevel method on it to set it to something else.
ReportTimestamp: true,
ReportCaller: true,
},
Expand Down
29 changes: 19 additions & 10 deletions pkg/stave/templates/initial_stavefile.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build stave
// +build stave

package main

Expand All @@ -8,37 +7,47 @@ import (
"os"
"os/exec"

"github.com/charmbracelet/log"
"github.com/yaklabco/stave/pkg/st" // st contains helpful utility functions, like Deps
"github.com/yaklabco/stave/pkg/stave/prettylog"
)

func init() { //nolint:gochecknoinits // This is a stavefile, we can have an init().
logHandler := prettylog.SetupPrettyLogger(os.Stdout)
if st.Debug() {
logHandler.SetLevel(log.DebugLevel)
}
}

// Default target to run when none is specified
// If not set, running stave will list available targets
// var Default = Build

// A build step that requires additional params, or platform specific steps for example
// A build step that requires additional params, or platform specific steps for example.
func Build() error {
st.Deps(InstallDeps)
fmt.Println("Building...")
_, _ = fmt.Println("Building...")
cmd := exec.Command("go", "build", "-o", "MyApp", ".")
return cmd.Run()
}

// A custom install step if you need your bin someplace other than go/bin
// A custom install step if you need your bin someplace other than go/bin.
func Install() error {
st.Deps(Build)
fmt.Println("Installing...")
_, _ = fmt.Println("Installing...")
return os.Rename("./MyApp", "/usr/bin/MyApp")
}

// Manage your deps, or running package managers.
func InstallDeps() error {
fmt.Println("Installing Deps...")
_, _ = fmt.Println("Installing Deps...")
cmd := exec.Command("go", "get", "github.com/stretchr/piglatin")
return cmd.Run()
}

// Clean up after yourself
func Clean() {
fmt.Println("Cleaning...")
os.RemoveAll("MyApp")
// Clean up after yourself.
func Clean() error {
_, _ = fmt.Println("Cleaning...")

return os.RemoveAll("MyApp")
}
Loading