release/dist: run yarn build before building CLI

This builds the assets for the new web client as part of our release
process. These assets will soon be embedded into the cmd/tailscale
binary, but are not actually done so yet.

Updates tailscale/corp#13775

Signed-off-by: Will Norris <will@tailscale.com>
This commit is contained in:
Will Norris 2023-08-16 12:21:39 -07:00 committed by Will Norris
parent 84b94b3146
commit 0fb95ec07d
4 changed files with 48 additions and 8 deletions

42
release/dist/dist.go vendored
View File

@ -43,6 +43,8 @@ type Build struct {
Tmp string Tmp string
// Go is the path to the Go binary to use for building. // Go is the path to the Go binary to use for building.
Go string Go string
// Yarn is the path to the yarn binary to use for building the web client assets.
Yarn string
// Version is the version info of the build. // Version is the version info of the build.
Version mkversion.VersionInfo Version mkversion.VersionInfo
// Time is the timestamp of the build. // Time is the timestamp of the build.
@ -79,15 +81,20 @@ func NewBuild(repo, out string) (*Build, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("finding module root: %w", err) return nil, fmt.Errorf("finding module root: %w", err)
} }
goTool, err := findGo(repo) goTool, err := findTool(repo, "go")
if err != nil { if err != nil {
return nil, fmt.Errorf("finding go binary: %w", err) return nil, fmt.Errorf("finding go binary: %w", err)
} }
yarnTool, err := findTool(repo, "yarn")
if err != nil {
return nil, fmt.Errorf("finding yarn binary: %w", err)
}
b := &Build{ b := &Build{
Repo: repo, Repo: repo,
Tmp: tmp, Tmp: tmp,
Out: out, Out: out,
Go: goTool, Go: goTool,
Yarn: yarnTool,
Version: mkversion.Info(), Version: mkversion.Info(),
Time: time.Now().UTC(), Time: time.Now().UTC(),
extra: map[any]any{}, extra: map[any]any{},
@ -180,6 +187,24 @@ func (b *Build) TmpDir() string {
return ret return ret
} }
// BuildWebClientAssets builds the JS and CSS assets used by the web client.
// Assets are built in the client/web/build directory and embedded in
// the cmd/tailscale binary.
func (b *Build) BuildWebClientAssets() error {
// Nothing in the web client assets is platform-specific,
// so we only need to build it once.
return b.Once("build-web-client-assets", func() error {
dir := filepath.Join(b.Repo, "client", "web")
if err := b.Command(dir, b.Yarn, "install").Run(); err != nil {
return err
}
if err := b.Command(dir, b.Yarn, "build").Run(); err != nil {
return err
}
return nil
})
}
// BuildGoBinary builds the Go binary at path and returns the path to the // BuildGoBinary builds the Go binary at path and returns the path to the
// binary. Builds are cached by path and env, so each build only happens once // binary. Builds are cached by path and env, so each build only happens once
// per process execution. // per process execution.
@ -303,16 +328,19 @@ func findModRoot(path string) (string, error) {
} }
} }
func findGo(path string) (string, error) { // findTool returns the path to the specified named tool.
toolGo := filepath.Join(path, "tool/go") // It first looks in the "tool" directory in the provided path,
if _, err := os.Stat(toolGo); err == nil { // then in the $PATH environment variable.
return toolGo, nil func findTool(path, name string) (string, error) {
tool := filepath.Join(path, "tool", name)
if _, err := os.Stat(tool); err == nil {
return tool, nil
} }
toolGo, err := exec.LookPath("go") tool, err := exec.LookPath(name)
if err != nil { if err != nil {
return "", err return "", err
} }
return toolGo, nil return tool, nil
} }
// FilterTargets returns the subset of targets that match any of the filters. // FilterTargets returns the subset of targets that match any of the filters.

View File

@ -144,6 +144,9 @@ func getSynologyBuilds(b *dist.Build) *synologyBuilds {
func (m *synologyBuilds) buildInnerPackage(b *dist.Build, dsmVersion int, goenv map[string]string) (*innerPkg, error) { func (m *synologyBuilds) buildInnerPackage(b *dist.Build, dsmVersion int, goenv map[string]string) (*innerPkg, error) {
key := []any{dsmVersion, goenv} key := []any{dsmVersion, goenv}
return m.innerPkgs.Do(key, func() (*innerPkg, error) { return m.innerPkgs.Do(key, func() (*innerPkg, error) {
if err := b.BuildWebClientAssets(); err != nil {
return nil, err
}
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", goenv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", goenv)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -53,6 +53,9 @@ func (t *tgzTarget) Build(b *dist.Build) ([]string, error) {
} else { } else {
filename = fmt.Sprintf("tailscale_%s_%s_%s.tgz", b.Version.Short, t.os(), t.arch()) filename = fmt.Sprintf("tailscale_%s_%s_%s.tgz", b.Version.Short, t.os(), t.arch())
} }
if err := b.BuildWebClientAssets(); err != nil {
return nil, err
}
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
@ -193,6 +196,9 @@ func (t *debTarget) Build(b *dist.Build) ([]string, error) {
return nil, errors.New("deb only supported on linux") return nil, errors.New("deb only supported on linux")
} }
if err := b.BuildWebClientAssets(); err != nil {
return nil, err
}
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err
@ -305,6 +311,9 @@ func (t *rpmTarget) Build(b *dist.Build) ([]string, error) {
return nil, errors.New("rpm only supported on linux") return nil, errors.New("rpm only supported on linux")
} }
if err := b.BuildWebClientAssets(); err != nil {
return nil, err
}
ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv) ts, err := b.BuildGoBinary("tailscale.com/cmd/tailscale", t.goEnv)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -21,7 +21,7 @@ fi
cachedir="$HOME/.cache/tailscale-yarn" cachedir="$HOME/.cache/tailscale-yarn"
tarball="${cachedir}.tar.gz" tarball="${cachedir}.tar.gz"
read -r want_rev < "$(dirname "$0")/yarn.rev" read -r want_rev < "./tool/yarn.rev"
got_rev="" got_rev=""
if [[ -x "${cachedir}/bin/yarn" ]]; then if [[ -x "${cachedir}/bin/yarn" ]]; then