diff options
| author | Xe Iaso <me@xeiaso.net> | 2025-04-07 10:11:31 -0400 |
|---|---|---|
| committer | Xe Iaso <me@xeiaso.net> | 2025-04-07 10:11:31 -0400 |
| commit | 458cf2e9044b98b1665006e38745a950b3dc83e9 (patch) | |
| tree | d855382e4c539f21c15a88a79f8ce50e6bcf45d3 | |
| parent | ea8b945a1af8603bbecf2fc2e398c321468bc650 (diff) | |
| download | x-458cf2e9044b98b1665006e38745a950b3dc83e9.tar.xz x-458cf2e9044b98b1665006e38745a950b3dc83e9.zip | |
cmd: add yeet tombstone
Signed-off-by: Xe Iaso <me@xeiaso.net>
| -rw-r--r-- | cmd/yeet/.gitignore | 2 | ||||
| -rw-r--r-- | cmd/yeet/README.md | 315 | ||||
| -rw-r--r-- | cmd/yeet/internal/git.go | 59 | ||||
| -rw-r--r-- | cmd/yeet/internal/mkdeb/mkdeb.go | 155 | ||||
| -rw-r--r-- | cmd/yeet/internal/mkrpm/mkrpm.go | 161 | ||||
| -rw-r--r-- | cmd/yeet/internal/mktarball/mktarball.go | 165 | ||||
| -rw-r--r-- | cmd/yeet/internal/pkgmeta/package.go | 36 | ||||
| -rw-r--r-- | cmd/yeet/main.go | 260 | ||||
| -rw-r--r-- | cmd/yeet/var/.gitignore | 2 | ||||
| -rw-r--r-- | cmd/yeet/yeetfile.js | 36 |
10 files changed, 1 insertions, 1190 deletions
diff --git a/cmd/yeet/.gitignore b/cmd/yeet/.gitignore deleted file mode 100644 index db38867..0000000 --- a/cmd/yeet/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.rpm -*.deb
\ No newline at end of file diff --git a/cmd/yeet/README.md b/cmd/yeet/README.md index f03973a..b814353 100644 --- a/cmd/yeet/README.md +++ b/cmd/yeet/README.md @@ -1,316 +1,3 @@ # yeet -Yeet out actions with maximum haste! Declare your build instructions as small JavaScript snippets and let er rip! - -## Usage - -To install the current program with `go install`: - -```js -// yeetfile.js -go.install(); -``` - -## Available functions - -Yeet uses [goja](https://pkg.go.dev/github.com/dop251/goja#section-readme) to execute JavaScript. As such, it does not have access to NPM or other external JavaScript libraries. You also cannot import code/data from other files. These are not planned for inclusion into yeet. If functionality is required, it should be added to yeet itself. - -To make it useful, yeet exposes a bunch of helper objects full of tools. These tools fall in a few categories, each has its own section. - -### `$` - -`$` lets you construct shell commands using [tagged templates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). This lets you build whatever shell commands you want by mixing Go and JavaScript values freely. - -Example: - -```js -$`CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -s -w -extldflags "-static" -X "within.website/x.Version=${git.tag()}"`; -``` - -### `docker` - -Aliases for `docker` commands. - -#### `docker.build` - -An alias for the `docker build` command. Builds a docker image in the current working directory's Dockerfile. - -Usage: - -`docker.build(tag);` - -```js -docker.build("ghcr.io/xe/site/bin"); -docker.push("ghcr.io/xe/site/bin"); -``` - -#### `docker.load` - -Loads an exported docker image by path into the local docker daemon. This is most useful when combined with tools like `nix.build`. - -Usage: - -`docker.load(path)` - -```js -nix.build(".#docker.xedn"); -docker.load("./result"); -docker.push("registry.fly.io/xedn:latest"); -fly.deploy(); -``` - -#### `docker.push` - -Pushes a docker image to a registry. Analogous to `docker push` in the CLI. - -Usage: - -`docker.push(tag);` - -```js -docker.build("ghcr.io/xe/site/bin"); -docker.push("ghcr.io/xe/site/bin"); -``` - -### `file` - -Helpers for filesystem access. - -#### `file.copy` - -Copies a file from one place to another. Analogous to the `cp` command on Linux. Automatically creates directories in the `dest` path if they don't exist. - -Usage: - -`file.copy(src, dest);` - -```js -file.copy("LICENSE", `${out}/usr/share/doc/LICENSE`); -``` - -#### `file.read` - -Reads a file into memory and returns it as a string. - -Usage: - -`file.read(path);` - -```js -const version = file.read("VERSION"); -``` - -#### `file.write` - -Writes the contents of the `data` string to a file with mode `0660`. - -Usage: - -`file.write(path, data);` - -```js -file.write("VERSION", git.tag()); -``` - -### `fly` - -Automation for [flyctl](https://github.com/superfly/flyctl). Soon this will also let you manage Machines with the [Machines API](https://docs.machines.dev). - -#### `fly.deploy` - -Runs the `fly deploy` command for you. - -Usage: - -`fly.deploy();` - -```js -docker.build("registry.fly.io/foobar"); -docker.push("registry.fly.io/foobar"); -fly.deploy(); -``` - -### `git` - -Helpers for the Git version control system. - -#### `git.repoRoot` - -Returns the repository root as a string. - -`git.repoRoot();` - -```js -const repoRoot = git.repoRoot(); - -file.copy(`${repoRoot}/LICENSE`, `${out}/usr/share/doc/yeet/LICENSE`); -``` - -#### `git.tag` - -Returns the output of `git describe --tags`. Useful for getting the "current version" of the repo, where the current version will likely be different forward in time than it is backwards in time. - -Usage: - -`git.tag();` - -```js -const version = git.tag(); -``` - -### `go` - -Helpers for the Go programming language. - -#### `go.build` - -Runs `go build` in the current working directory with any extra arguments passed in. This is useful for building and installing Go programs in an RPM build context. - -Usage: - -`go.build(args);` - -```js -go.build("-o", `${out}/usr/bin/`); -``` - -#### `go.install` - -Runs `go install`. Not useful for cross-compilation. - -Usage: - -`go.install();` - -```js -go.install(); -``` - -### `rpm` - -Helpers for building RPM packages and docker images out of a constellation of RPM packages. - -#### `rpm.build` - -Builds an RPM package with a descriptor object. See the RPM packages section for more information. The important part of this is your `build` function. The `build` function is what will turn your package source code into an executable in `out` somehow. Everything in `out` corresponds 1:1 with paths in the resulting RPM. - -The resulting RPM path will be returned as a string. - -Usage: - -`rpm.build(package);` - -```js -["amd64", "arm64"].forEach((goarch) => - rpm.build({ - name: "yeet", - description: "Yeet out actions with maximum haste!", - homepage: "https://within.website", - license: "CC0", - goarch, - - build: (out) => { - go.build("-o", `${out}/usr/bin/`); - }, - }) -); -``` - -### `yeet` - -This contains various "other" functions that don't have a good place to put them. - -#### `yeet.cwd` - -The current working directory. This is a constant value and is not updated at runtime. - -Usage: - -```js -log.println(yeet.cwd); -``` - -#### `yeet.dateTag` - -A constant string representing the time that yeet was started in UTC. It is formatted in terms of `YYYYmmDDhhMM`. This is not updated at runtime. You can use it for a "unique" value per invocation of yeet (assuming you aren't a time traveler). - -Usage: - -```js -docker.build(`ghcr.io/xe/site/bin:${git.tag()}-${yeet.dateTag}`); -``` - -#### `yeet.run` / `yeet.runcmd` - -Runs an arbitrary command and returns any output as a string. - -Usage: - -`yeet.run(cmd, arg1, arg2, ...);` - -```js -yeet.run( - "protoc", - "--proto-path=.", - `--proto-path=${git.repoRoot()}/proto`, - "foo.proto" -); -``` - -#### `yeet.setenv` - -Sets an environment variable for the process yeet is running in and all children. - -Usage: - -`yeet.setenv(key, val);` - -```js -yeet.setenv("GOOS", "linux"); -``` - -#### `yeet.goos` / `yeet.goarch` - -The GOOS/GOARCH value that yeet was built for. This typically corresponds with the OS and CPU architecture that yeet is running on. - -## Building RPM Packages - -When using the `rpm.build` function, you can create RPM packages from arbitrary yeet expressions. This allows you to create RPM packages from a macOS or other Linux system. As an example, here is how the yeet RPMs are built: - -```js -["amd64", "arm64"].forEach((goarch) => - rpm.build({ - name: "yeet", - description: "Yeet out actions with maximum haste!", - homepage: "https://within.website", - license: "CC0", - goarch: goarch, - - build: (out) => { - go.build("-o", `${out}/usr/bin/`); - }, - }) -); -``` - -### Build settings - -The following settings are supported: - -| Name | Example | Description | -| :------------ | :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | -| `name` | `xeiaso.net-yeet` | The unique name of the package. | -| `version` | `1.0.0` | The version of the package, if not set then it will be inferred from the git version. | -| `description` | `Yeet out scripts with haste!` | The human-readable description of the package. | -| `homepage` | `https://xeiaso.net` | The URL for the homepage of the package. | -| `group` | `Network` | If set, the RPM group that this package belongs to. | -| `license` | `MIT` | The license that the contents of this package is under. | -| `goarch` | `amd64` / `arm64` | The GOARCH value corresponding to the architecture that the RPM is being built for. If you want to build a `noarch` package, put `any` here. | -| `replaces` | `["foo", "bar"]` | Any packages that this package conflicts with or replaces. | -| `depends` | `["foo", "bar"]` | Any packages that this package depends on (such as C libraries for CGo code). | -| `emptyDirs` | `["/var/lib/yeet"]` | Any empty directories that should be created when the package is installed. | -| `configFiles` | `{"./.env.example": "/var/lib/yeet/.env"}` | Any configuration files that should be copied over on install, but managed by administrators after installation. | - -## Support - -For support, please [subscribe to me on Patreon](https://patreon.com/cadey) and ask in the `#yeet` channel. You may open GitHub issues if you wish, but I do not often look at them. +Moved to [TecharoHQ/yeet](https://github.com/TecharoHQ/yeet). diff --git a/cmd/yeet/internal/git.go b/cmd/yeet/internal/git.go deleted file mode 100644 index 6ed6127..0000000 --- a/cmd/yeet/internal/git.go +++ /dev/null @@ -1,59 +0,0 @@ -package internal - -import ( - "context" - "flag" - "os" - "path/filepath" - - "github.com/Songmu/gitconfig" - "within.website/x/internal/yeet" -) - -var ( - GPGKeyFile = flag.String("gpg-key-file", gpgKeyFileLocation(), "GPG key file to sign the package") - GPGKeyID = flag.String("gpg-key-id", "", "GPG key ID to sign the package") - GPGKeyPassword = flag.String("gpg-key-password", "", "GPG key password to sign the package") - UserName = flag.String("git-user-name", GitUserName(), "user name in Git") - UserEmail = flag.String("git-user-email", GitUserEmail(), "user email in Git") -) - -const ( - fallbackName = "Mimi Yasomi" - fallbackEmail = "mimi@techaro.lol" -) - -func gpgKeyFileLocation() string { - folder, err := os.UserConfigDir() - if err != nil { - return "" - } - - return filepath.Join(folder, "within.website", "x", "yeet", "key.asc") -} - -func GitUserName() string { - name, err := gitconfig.User() - if err != nil { - return fallbackName - } - - return name -} - -func GitUserEmail() string { - email, err := gitconfig.Email() - if err != nil { - return fallbackEmail - } - - return email -} - -func GitVersion() string { - vers, err := yeet.GitTag(context.Background()) - if err != nil { - panic(err) - } - return vers[1:] -} diff --git a/cmd/yeet/internal/mkdeb/mkdeb.go b/cmd/yeet/internal/mkdeb/mkdeb.go deleted file mode 100644 index 6da999a..0000000 --- a/cmd/yeet/internal/mkdeb/mkdeb.go +++ /dev/null @@ -1,155 +0,0 @@ -package mkdeb - -import ( - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - - "github.com/goreleaser/nfpm/v2" - _ "github.com/goreleaser/nfpm/v2/deb" - "github.com/goreleaser/nfpm/v2/files" - "within.website/x/cmd/yeet/internal" - "within.website/x/cmd/yeet/internal/pkgmeta" -) - -func Build(p pkgmeta.Package) (foutpath string, err error) { - defer func() { - if r := recover(); r != nil { - if err, ok := r.(error); ok { - slog.Error("mkrpm: error while building", "err", err) - } else { - err = fmt.Errorf("%v", r) - slog.Error("mkrpm: error while building", "err", err) - } - } - }() - - os.MkdirAll("./var", 0755) - os.WriteFile(filepath.Join("./var", ".gitignore"), []byte("*\n!.gitignore"), 0644) - - if p.Version == "" { - p.Version = internal.GitVersion() - } - - dir, err := os.MkdirTemp("", "yeet-mkdeb") - if err != nil { - return "", fmt.Errorf("mkrpm: can't make temporary directory") - } - defer os.RemoveAll(dir) - os.MkdirAll(dir, 0755) - - defer func() { - os.Setenv("GOARCH", runtime.GOARCH) - os.Setenv("GOOS", runtime.GOOS) - }() - os.Setenv("GOARCH", p.Goarch) - os.Setenv("GOOS", "linux") - - p.Build(pkgmeta.BuildInput{ - Output: dir, - Bin: filepath.Join(dir, "usr", "bin"), - Doc: filepath.Join(dir, "usr", "share", "doc"), - Etc: filepath.Join(dir, "etc", p.Name), - Man: filepath.Join(dir, "usr", "share", "man"), - Systemd: filepath.Join(dir, "usr", "lib", "systemd", "system"), - }) - - var contents files.Contents - - for _, d := range p.EmptyDirs { - if d == "" { - continue - } - - contents = append(contents, &files.Content{Type: files.TypeDir, Destination: d}) - } - - for repoPath, osPath := range p.ConfigFiles { - contents = append(contents, &files.Content{ - Type: files.TypeConfig, - Source: repoPath, - Destination: osPath, - }) - } - - for repoPath, rpmPath := range p.Documentation { - contents = append(contents, &files.Content{ - Type: files.TypeFile, - Source: repoPath, - Destination: filepath.Join("/usr/share/doc", p.Name, rpmPath), - }) - } - - for repoPath, rpmPath := range p.Files { - contents = append(contents, &files.Content{ - Type: files.TypeFile, - Source: repoPath, - Destination: rpmPath, - }) - } - - if err := filepath.Walk(dir, func(path string, stat os.FileInfo, err error) error { - if err != nil { - return err - } - - if stat.IsDir() { - return nil - } - - contents = append(contents, &files.Content{Type: files.TypeFile, Source: path, Destination: path[len(dir)+1:]}) - - return nil - }); err != nil { - return "", fmt.Errorf("mkdeb: can't walk output directory: %w", err) - } - - info := nfpm.WithDefaults(&nfpm.Info{ - Name: p.Name, - Version: p.Version, - Arch: p.Goarch, - Platform: "linux", - Description: p.Description, - Maintainer: fmt.Sprintf("%s <%s>", *internal.UserName, *internal.UserEmail), - Homepage: p.Homepage, - License: p.License, - Overridables: nfpm.Overridables{ - Contents: contents, - Depends: p.Depends, - Recommends: p.Recommends, - Replaces: p.Replaces, - Conflicts: p.Replaces, - }, - }) - - info.Overridables.RPM.Group = p.Group - - if *internal.GPGKeyID != "" { - slog.Debug("using GPG key", "file", *internal.GPGKeyFile, "id", *internal.GPGKeyID) - info.Overridables.Deb.Signature.KeyFile = *internal.GPGKeyFile - info.Overridables.Deb.Signature.KeyID = internal.GPGKeyID - info.Overridables.Deb.Signature.KeyPassphrase = *internal.GPGKeyPassword - } - - pkg, err := nfpm.Get("deb") - if err != nil { - return "", fmt.Errorf("mkdeb: can't get RPM packager: %w", err) - } - - foutpath = pkg.ConventionalFileName(info) - fout, err := os.Create(filepath.Join("./var", foutpath)) - if err != nil { - return "", fmt.Errorf("mkdeb: can't create output file: %w", err) - } - defer fout.Close() - - if err := pkg.Package(info, fout); err != nil { - return "", fmt.Errorf("mkdeb: can't build package: %w", err) - } - - slog.Info("built package", "name", p.Name, "arch", p.Goarch, "version", p.Version, "path", fout.Name()) - - return foutpath, err -} diff --git a/cmd/yeet/internal/mkrpm/mkrpm.go b/cmd/yeet/internal/mkrpm/mkrpm.go deleted file mode 100644 index eae0778..0000000 --- a/cmd/yeet/internal/mkrpm/mkrpm.go +++ /dev/null @@ -1,161 +0,0 @@ -package mkrpm - -import ( - "fmt" - "log/slog" - "os" - "path/filepath" - "runtime" - - "github.com/goreleaser/nfpm/v2" - "github.com/goreleaser/nfpm/v2/files" - _ "github.com/goreleaser/nfpm/v2/rpm" - "within.website/x/cmd/yeet/internal" - "within.website/x/cmd/yeet/internal/pkgmeta" -) - -func Build(p pkgmeta.Package) (foutpath string, err error) { - defer func() { - if r := recover(); r != nil { - if err, ok := r.(error); ok { - slog.Error("mkrpm: error while building", "err", err) - } else { - err = fmt.Errorf("%v", r) - slog.Error("mkrpm: error while building", "err", err) - } - } - }() - - os.MkdirAll("./var", 0755) - os.WriteFile(filepath.Join("./var", ".gitignore"), []byte("*\n!.gitignore"), 0644) - - if p.Version == "" { - p.Version = internal.GitVersion() - } - if p.Platform == "" { - p.Platform = "linux" - } - - dir, err := os.MkdirTemp("", "yeet-mkrpm") - if err != nil { - return "", fmt.Errorf("mkrpm: can't make temporary directory") - } - defer os.RemoveAll(dir) - os.MkdirAll(dir, 0755) - - cgoEnabled := os.Getenv("CGO_ENABLED") - defer func() { - os.Setenv("GOARCH", runtime.GOARCH) - os.Setenv("GOOS", runtime.GOOS) - os.Setenv("CGO_ENABLED", cgoEnabled) - }() - os.Setenv("GOARCH", p.Goarch) - os.Setenv("GOOS", p.Platform) - os.Setenv("CGO_ENABLED", "0") - - p.Build(pkgmeta.BuildInput{ - Output: dir, - Bin: filepath.Join(dir, "usr", "bin"), - Doc: filepath.Join(dir, "usr", "share", "doc"), - Etc: filepath.Join(dir, "etc", p.Name), - Man: filepath.Join(dir, "usr", "share", "man"), - Systemd: filepath.Join(dir, "usr", "lib", "systemd", "system"), - }) - - var contents files.Contents - - for _, d := range p.EmptyDirs { - if d == "" { - continue - } - - contents = append(contents, &files.Content{Type: files.TypeDir, Destination: d}) - } - - for repoPath, rpmPath := range p.ConfigFiles { - contents = append(contents, &files.Content{ - Type: files.TypeConfig, - Source: repoPath, - Destination: rpmPath, - }) - } - - for repoPath, rpmPath := range p.Documentation { - contents = append(contents, &files.Content{ - Type: files.TypeRPMDoc, - Source: repoPath, - Destination: filepath.Join("/usr/share/doc", p.Name, rpmPath), - }) - } - - for repoPath, rpmPath := range p.Files { - contents = append(contents, &files.Content{ - Type: files.TypeFile, - Source: repoPath, - Destination: rpmPath, - }) - } - - if err := filepath.Walk(dir, func(path string, stat os.FileInfo, err error) error { - if err != nil { - return err - } - - if stat.IsDir() { - return nil - } - - contents = append(contents, &files.Content{Type: files.TypeFile, Source: path, Destination: path[len(dir)+1:]}) - - return nil - }); err != nil { - return "", fmt.Errorf("mkrpm: can't walk output directory: %w", err) - } - - info := nfpm.WithDefaults(&nfpm.Info{ - Name: p.Name, - Version: p.Version, - Arch: p.Goarch, - Platform: p.Platform, - Description: p.Description, - Maintainer: fmt.Sprintf("%s <%s>", *internal.UserName, *internal.UserEmail), - Homepage: p.Homepage, - License: p.License, - Overridables: nfpm.Overridables{ - Contents: contents, - Depends: p.Depends, - Recommends: p.Recommends, - Replaces: p.Replaces, - Conflicts: p.Replaces, - }, - }) - - info.Overridables.RPM.Group = p.Group - - if *internal.GPGKeyID != "" { - slog.Debug("using GPG key", "file", *internal.GPGKeyFile, "id", *internal.GPGKeyID, "password", *internal.GPGKeyPassword) - info.Overridables.RPM.Signature.KeyFile = *internal.GPGKeyFile - info.Overridables.RPM.Signature.KeyID = internal.GPGKeyID - info.Overridables.RPM.Signature.KeyPassphrase = *internal.GPGKeyPassword - } - - pkg, err := nfpm.Get("rpm") - if err != nil { - return "", fmt.Errorf("mkrpm: can't get RPM packager: %w", err) - } - - foutpath = pkg.ConventionalFileName(info) - fout, err := os.Create(filepath.Join("./var", foutpath)) - if err != nil { - return "", fmt.Errorf("mkrpm: can't create output file: %w", err) - } - defer fout.Close() - - if err := pkg.Package(info, fout); err != nil { - return "", fmt.Errorf("mkrpm: can't build package: %w", err) - } - - slog.Info("built package", "name", p.Name, "arch", p.Goarch, "version", p.Version, "path", fout.Name()) - - return foutpath, err -} diff --git a/cmd/yeet/internal/mktarball/mktarball.go b/cmd/yeet/internal/mktarball/mktarball.go deleted file mode 100644 index 06ee2b7..0000000 --- a/cmd/yeet/internal/mktarball/mktarball.go +++ /dev/null @@ -1,165 +0,0 @@ -package mktarball - -import ( - "archive/tar" - "compress/gzip" - "fmt" - "io" - "log/slog" - "os" - "path/filepath" - "runtime" - - "within.website/x/cmd/yeet/internal" - "within.website/x/cmd/yeet/internal/pkgmeta" -) - -func defaultFname(p pkgmeta.Package) string { - return fmt.Sprintf("%s-%s-%s-%s", p.Name, p.Version, p.Platform, p.Goarch) -} - -func Build(p pkgmeta.Package) (foutpath string, err error) { - defer func() { - if r := recover(); r != nil { - if err, ok := r.(error); ok { - slog.Error("mkrpm: error while building", "err", err) - } else { - err = fmt.Errorf("%v", r) - slog.Error("mkrpm: error while building", "err", err) - } - } - }() - - os.MkdirAll("./var", 0755) - os.WriteFile(filepath.Join("./var", ".gitignore"), []byte("*\n!.gitignore"), 0644) - - if p.Version == "" { - p.Version = internal.GitVersion() - } - if p.Platform == "" { - p.Platform = "linux" - } - - dir, err := os.MkdirTemp("", "yeet-mktarball") - if err != nil { - return "", fmt.Errorf("can't make temporary directory") - } - defer os.RemoveAll(dir) - - folderName := defaultFname(p) - if p.Filename != nil { - folderName = p.Filename(p) - } - - pkgDir := filepath.Join(dir, folderName) - os.MkdirAll(pkgDir, 0755) - - fname := filepath.Join("var", folderName+".tar.gz") - fout, err := os.Create(fname) - if err != nil { - return "", fmt.Errorf("can't make output file: %w", err) - } - defer fout.Close() - - gw, err := gzip.NewWriterLevel(fout, 9) - if err != nil { - return "", fmt.Errorf("can't make gzip writer: %w", err) - } - defer gw.Close() - - tw := tar.NewWriter(gw) - defer tw.Close() - - cgoEnabled := os.Getenv("CGO_ENABLED") - defer func() { - os.Setenv("GOARCH", runtime.GOARCH) - os.Setenv("GOOS", runtime.GOOS) - os.Setenv("CGO_ENABLED", cgoEnabled) - }() - os.Setenv("GOARCH", p.Goarch) - os.Setenv("GOOS", p.Platform) - os.Setenv("CGO_ENABLED", "0") - - bi := pkgmeta.BuildInput{ - Output: pkgDir, - Bin: filepath.Join(pkgDir, "bin"), - Doc: filepath.Join(pkgDir, "doc"), - Etc: filepath.Join(pkgDir, "run"), - Man: filepath.Join(pkgDir, "man"), - Systemd: filepath.Join(pkgDir, "run"), - } - - os.MkdirAll(bi.Doc, 0755) - os.WriteFile(filepath.Join(bi.Doc, "VERSION"), []byte(p.Version+"\n"), 0666) - - p.Build(bi) - - for src, dst := range p.ConfigFiles { - if err := Copy(src, filepath.Join(bi.Etc, dst)); err != nil { - return "", fmt.Errorf("can't copy %s to %s: %w", src, dst, err) - } - } - - for src, dst := range p.Documentation { - fname := filepath.Join(bi.Doc, dst) - if filepath.Base(fname) == "README.md" { - fname = filepath.Join(pkgDir, "README.md") - } - - if err := Copy(src, fname); err != nil { - return "", fmt.Errorf("can't copy %s to %s: %w", src, dst, err) - } - } - - root, err := os.OpenRoot(dir) - if err != nil { - return "", fmt.Errorf("can't open root FS %s: %w", dir, err) - } - - if err := tw.AddFS(root.FS()); err != nil { - return "", fmt.Errorf("can't copy built files to tarball: %w", err) - } - - slog.Info("built package", "name", p.Name, "arch", p.Goarch, "version", p.Version, "path", fout.Name()) - - return fname, nil -} - -// Copy copies the contents of the file at srcpath to a regular file -// at dstpath. If the file named by dstpath already exists, it is -// truncated. The function does not copy the file mode, file -// permission bits, or file attributes. -func Copy(srcpath, dstpath string) (err error) { - r, err := os.Open(srcpath) - if err != nil { - return err - } - defer r.Close() // ignore error: file was opened read-only. - - st, err := r.Stat() - if err != nil { - return err - } - - os.MkdirAll(filepath.Dir(dstpath), 0755) - - w, err := os.Create(dstpath) - if err != nil { - return err - } - - if err := w.Chmod(st.Mode()); err != nil { - return err - } - - defer func() { - // Report the error, if any, from Close, but do so - // only if there isn't already an outgoing error. - if c := w.Close(); err == nil { - err = c - } - }() - - _, err = io.Copy(w, r) - return err -} diff --git a/cmd/yeet/internal/pkgmeta/package.go b/cmd/yeet/internal/pkgmeta/package.go deleted file mode 100644 index f955c6e..0000000 --- a/cmd/yeet/internal/pkgmeta/package.go +++ /dev/null @@ -1,36 +0,0 @@ -package pkgmeta - -type Package struct { - Name string `json:"name"` - Version string `json:"version"` - Description string `json:"description"` - Homepage string `json:"homepage"` - Group string `json:"group"` - License string `json:"license"` - Platform string `json:"platform"` // if not set, default to linux - Goarch string `json:"goarch"` - Replaces []string `json:"replaces"` - Depends []string `json:"depends"` - Recommends []string `json:"recommends"` - - EmptyDirs []string `json:"emptyDirs"` // rpm destination path - ConfigFiles map[string]string `json:"configFiles"` // pwd-relative source path, rpm destination path - Documentation map[string]string `json:"documentation"` // pwd-relative source path, file in /usr/share/doc/$Name - Files map[string]string `json:"files"` // pwd-relative source path, rpm destination path - - Build func(BuildInput) `json:"build"` - Filename func(Package) string `json:"mkFilename"` -} - -type BuildInput struct { - Output string `json:"out"` - Bin string `json:"bin"` - Doc string `json:"doc"` - Etc string `json:"etc"` - Man string `json:"man"` - Systemd string `json:"systemd"` -} - -func (b BuildInput) String() string { - return b.Output -} diff --git a/cmd/yeet/main.go b/cmd/yeet/main.go deleted file mode 100644 index 9fa8db1..0000000 --- a/cmd/yeet/main.go +++ /dev/null @@ -1,260 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "log" - "log/slog" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - - "al.essio.dev/pkg/shellescape" - "github.com/dop251/goja" - yeetinternal "within.website/x/cmd/yeet/internal" - "within.website/x/cmd/yeet/internal/mkdeb" - "within.website/x/cmd/yeet/internal/mkrpm" - "within.website/x/cmd/yeet/internal/mktarball" - "within.website/x/cmd/yeet/internal/pkgmeta" - "within.website/x/internal" - "within.website/x/internal/appsluggr" - "within.website/x/internal/kahless" - "within.website/x/internal/yeet" - "within.website/x/writer" -) - -var ( - fname = flag.String("fname", "yeetfile.js", "filename for the yeetfile") - flyctl = flag.String("flyctl-path", flyctlPath(), "path to flyctl binary") -) - -func flyctlPath() string { - home, err := os.UserHomeDir() - if err != nil { - return "flyctl" - } - - homedirPath := filepath.Join(home, ".fly", "bin", "fly") - - if _, err := os.Stat(homedirPath); err != nil { - return "flyctl" - } - - return homedirPath -} - -func runcmd(cmdName string, args ...string) string { - ctx := context.Background() - - slog.Debug("running command", "cmd", cmdName, "args", args) - - result, err := yeet.Output(ctx, cmdName, args...) - if err != nil { - panic(err) - } - - return result -} - -func gittag() string { - ctx := context.Background() - - tag, err := yeet.GitTag(ctx) - if err != nil { - panic(err) - } - - return tag -} - -func dockerload(fname string) { - if fname == "" { - fname = "./result" - } - yeet.DockerLoadResult(context.Background(), fname) -} - -func dockerbuild(tag string, args ...string) { - yeet.DockerBuild(context.Background(), yeet.WD, tag, args...) -} - -func dockerpush(image string) { - yeet.DockerPush(context.Background(), image) -} - -func flydeploy() { - runcmd(*flyctl, "deploy", "--now") -} - -func slugbuild(bin string, extraFiles map[string]string) string { - result := fmt.Sprintf("%s-%s.tar.gz", bin, yeet.DateTag) - appsluggr.Must(bin, result, extraFiles) - os.Remove(bin) - return result -} - -func slugpush(fname string) string { - fin, err := os.Open(fname) - if err != nil { - panic(err) - } - defer fin.Close() - pubURL, err := kahless.CopySlug(fname, fin) - if err != nil { - panic(err) - } - - os.Remove(fname) - - return pubURL -} - -func buildShellCommand(literals []string, exprs ...any) string { - var sb strings.Builder - for i, value := range exprs { - sb.WriteString(literals[i]) - sb.WriteString(shellescape.Quote(fmt.Sprint(value))) - } - - sb.WriteString(literals[len(literals)-1]) - - return sb.String() -} - -func runShellCommand(literals []string, exprs ...any) string { - shPath, err := exec.LookPath("sh") - if err != nil { - panic(err) - } - - cmd := buildShellCommand(literals, exprs...) - - slog.Debug("running command", "cmd", cmd) - output, err := yeet.Output(context.Background(), shPath, "-c", cmd) - if err != nil { - panic(err) - } - - return output -} - -func hostname() string { - result, err := os.Hostname() - if err != nil { - panic(err) - } - return result -} - -func main() { - internal.HandleStartup() - - vm := goja.New() - vm.SetFieldNameMapper(goja.TagFieldNameMapper("json", true)) - - defer func() { - if r := recover(); r != nil { - slog.Error("error in JS", "err", r) - } - }() - - data, err := os.ReadFile(*fname) - if err != nil { - log.Fatal(err) - } - - lg := log.New(writer.LineSplitting(writer.PrefixWriter("[yeet] ", os.Stdout)), "", 0) - - vm.Set("$", runShellCommand) - - vm.Set("deb", map[string]any{ - "build": func(p pkgmeta.Package) string { - foutpath, err := mkdeb.Build(p) - if err != nil { - panic(err) - } - return foutpath - }, - }) - - vm.Set("docker", map[string]any{ - "build": dockerbuild, - "load": dockerload, - "push": dockerpush, - }) - - vm.Set("file", map[string]any{ - "install": func(src, dst string) { - if err := mktarball.Copy(src, dst); err != nil { - panic(err) - } - }, - }) |
