diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..d4c9a07 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,30 @@ +name: Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.19 + + - name: Build + run: | + go get ./... + go build -v ./... -trimpath -buildmode=plugin + + - name: Upload a Release Asset + uses: softprops/action-gh-release@v1 + with: + files: vib-plugin.so diff --git a/README.md b/README.md new file mode 100644 index 0000000..b9ee67b --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ + +# vib-plugin + +A template to create plugins for [vib](https://github.com/vanilla-os/vib) + +## Usage +To use this template, simply fork it and change the module name in go.mod. + +Then you can modify the source in src/plugin.go to create your own plugin. + +## Plugin requirements +src/plugin.go explains all requirements for plugins with code examples. +A short tldr: +- vib requires `BuildModule(interface{}, recipe *api.Recipe*) (string, error)` to be available as it is used as the entrypoint for the plugin. Any other functions can be freely declared and will not be used by vib +- Each plugin needs to have a custom struct for the module, with at least two mandatory values: `Name string` and `Type string` +- It is recommended, but not required, to use the api functions for source definition or downloading sources + +## Building +NOTE: Plugins will have to be compiled with the same go version as vib, for builds from vanilla-os, this version is 1.19, it is recommended to use podman/docker or the github workflow to build the plugins. + +Plugins can be built with `go build -trimpath -buildmode=plugin`, which will produce a .so file. +To use the plugin, the .so file has to be moved into the plugins/ directory of the vib recipe. +Plugins are only loaded when required, if a recipe never uses plugin example, example.so will never be loaded. + +This template contains a github workflow that can build the plugin with the right arguments automatically. +Otherwise one can use podman/docker to build the plugin: +`docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.19 go build -trimpath -buildmode=plugin -v` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4b78fda --- /dev/null +++ b/go.mod @@ -0,0 +1,9 @@ +module github.com// // remember to change this according to your needs! + + +go 1.21 + +require ( + github.com/mitchellh/mapstructure v1.5.0 + github.com/vanilla-os/vib/api v0.0.0-20231203164136-c843eaca2af6 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1602e93 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/vanilla-os/vib/api v0.0.0-20231203164136-c843eaca2af6 h1:J9h3w+pi9ZhhXDS+d/9IxWNbJ4hSMlUU8HFrF5RTtWE= +github.com/vanilla-os/vib/api v0.0.0-20231203164136-c843eaca2af6/go.mod h1:vjJzDfFxfFHN5O2hcMwGM9De3+H9gGa00Pr3Um6EmCA= diff --git a/plugin.go b/plugin.go new file mode 100644 index 0000000..e00865e --- /dev/null +++ b/plugin.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "github.com/mitchellh/mapstructure" + "github.com/vanilla-os/vib/api" +) + +type ExampleModule struct { + // Mandatory values, your plugin will not work if these are not present! + Name string `json:"name"` + Type string `json:"type"` + + // Additional values such as Source can be added here + Source api.Source +} + +// Plugins can define extra functions that are used internally +// Vib will never call any function other than BuildModule +func fetchSources(source api.Source, name string, recipe *api.Recipe) error { + // The plugin api offers functions to download sources + // To be able to use them, the use of api.Source for + // source definition is recommended + // Using these functions to fetch sources is not required + // but highly recommended to ensure sources are always in the right directory + err := api.DownloadSource(recipe.DownloadsPath, source, name) + if err != nil { + return err + } + err = api.MoveSource(recipe.DownloadsPath, recipe.SourcesPath, source, name) + return err +} + +// This is the entry point for plugins that vib calls +// The arguments are required to be (interface{}, recipe) => (string, error) +func BuildModule(moduleInterface interface{}, recipe *api.Recipe) (string, error) { + // It is advisable to convert the interface to an actual struct + // The use of mapstructure for this is recommended, but not required + var module ExampleModule + err := mapstructure.Decode(moduleInterface, &module) + if err != nil { + return "", err + } + err = fetchSources(module.Source, module.Name, recipe) + if err != nil { + return "", err + } + + // The sources will be made available at /sources/ during build + // if the plugins requires manually downloaded sources, they will + // be available in /sources/ + cmd := fmt.Sprintf("cd /sources/%s && cp * /etc/%s", module.Name, module.Name) + + return cmd, nil +}