flamenco/magefiles/addonpacker.go
Sybren A. Stüvel 5f37bcb629 Build with Magefile (#104341)
Convert most of the code in `Makefile` to [Magefile](https://magefile.org/):

This makes it possible to build Flamenco without `make` (and the POSIX environment/commands it expect) by running:

```bash
$ go run mage.go webappInstallDeps  # Only on the first build.
$ go run mage.go build
```

More efficient builds are possible with other commands, and some release-related commands still require `make`. At least the barrier to entry should be considerably lower (compared to having to install Make + Cygwin/MSYS2 on Windows).

Fix: #102633

This does not port the building of release packages, so it doesn't address #102671.

### Main Targets

| Target   | Description                                                                     |
|----------|---------------------------------------------------------------------------------|
| build    | Build Flamenco Manager and Flamenco Worker, including the webapp and the add-on |
| check    | Run unit tests, check for vulnerabilities, and run the linter                   |
| clean    | Remove executables and other build output                                       |
| generate | Generate code (OpenAPI and test mocks)                                          |

### All Targets

Get these via `go run mage.go -l`:

```
Targets:
  build                           Flamenco Manager and Flamenco Worker, including the webapp and the add-on
  check                           Run unit tests, check for vulnerabilities, and run the linter
  clean                           Remove executables and other build output
  flamencoManager                 Build Flamenco Manager with the webapp and add-on ZIP embedded
  flamencoManagerWithoutWebapp    Only build the Flamenco Manager executable, do not rebuild the webapp
  flamencoWorker                  Build the Flamenco Worker executable
  generate                        code (OpenAPI and test mocks)
  generateGo                      Generate Go code for Flamenco Manager and Worker
  generateJS                      Generate JavaScript code for the webapp
  generatePy                      Generate Python code for the add-on
  govulncheck                     Check for known vulnerabilities.
  staticcheck                     Analyse the source code.
  test                            Run unit tests
  version                         Show which version information would be embedded in executables
  vet                             Run `go vet`
  webappInstallDeps               Use Yarn to install the webapp's NodeJS dependencies
  webappStatic                    Build the webapp as static files that can be served
```

Co-authored-by: Mateus Abelli <mateusabelli@gmail.com>
Reviewed-on: #104341
2024-10-04 21:59:44 +02:00

109 lines
2.6 KiB
Go

//go:build mage
package main
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"archive/zip"
"compress/flate"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"projects.blender.org/studio/flamenco/internal/appinfo"
)
func packAddon(filename string) error {
outfile, err := filepath.Abs(filename)
if err != nil {
return fmt.Errorf("unable make output file path absolute: %w", err)
}
// Open the output file.
zipFile, err := os.Create(outfile)
if err != nil {
return fmt.Errorf("error creating file %s: %w", outfile, err)
}
defer zipFile.Close()
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
zipWriter.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(out, flate.BestCompression)
})
basePath, err := filepath.Abs("./addon") // os.Getwd()
if err != nil {
return fmt.Errorf("error getting current working directory: %w", err)
}
// Copy all the files into the ZIP.
addToZip := func(path string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("error received from filepath.WalkDir: %w", err)
}
// Construct the path inside the ZIP file.
relpath, err := filepath.Rel(basePath, path)
if err != nil {
return fmt.Errorf("making %s relative to %s: %w", path, basePath, err)
}
if d.IsDir() {
switch {
case filepath.Base(path) == "__pycache__":
return fs.SkipDir
case relpath == filepath.Join("flamenco", "manager", "docs"):
return fs.SkipDir
case strings.HasPrefix(filepath.Base(path), "."):
// Skip directories like .mypy_cache, etc.
return fs.SkipDir
default:
// Just recurse into this directory.
return nil
}
}
// Read the file's contents. These are just Python files and maybe a Wheel,
// nothing huge.
contents, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("reading %s: %w", path, err)
}
// Write into the ZIP file.
fileInZip, err := zipWriter.Create(relpath)
if err != nil {
return fmt.Errorf("creating %s in ZIP: %w", relpath, err)
}
_, err = fileInZip.Write(contents)
if err != nil {
return fmt.Errorf("writing to %s in ZIP: %w", relpath, err)
}
return nil
}
if err := filepath.WalkDir(filepath.Join(basePath, "flamenco"), addToZip); err != nil {
return fmt.Errorf("error filling ZIP file: %w", err)
}
comment := fmt.Sprintf("%s add-on for Blender, version %s",
appinfo.ApplicationName,
appinfo.ApplicationVersion,
)
if err := zipWriter.SetComment(comment); err != nil {
return fmt.Errorf("error setting ZIP comment: %w", err)
}
if err := zipWriter.Close(); err != nil {
return fmt.Errorf("error closing ZIP file: %w", err)
}
return nil
}