Compare commits
7 Commits
0.9.32-alp
...
hooks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
422035b5b7 | ||
|
|
4547c0b1eb | ||
|
|
bb5173deb2 | ||
|
|
5b4eaf5ff2 | ||
|
|
f049ebd383 | ||
|
|
9904a979e2 | ||
|
|
001712f9ad |
@@ -1,6 +1,6 @@
|
||||
run:
|
||||
deadline: 10m
|
||||
timeout: 10m
|
||||
deadline: 20m
|
||||
timeout: 20m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
skip-dirs:
|
||||
|
||||
15
assets/dockerfiles/base/node/package-lock.json
generated
vendored
15
assets/dockerfiles/base/node/package-lock.json
generated
vendored
@@ -1,13 +1,26 @@
|
||||
{
|
||||
"name": "aok",
|
||||
"name": "fx-node-base",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@koa/cors": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@koa/cors/-/cors-2.2.3.tgz",
|
||||
"integrity": "sha512-tCVVXa39ETsit5kGBtEWWimjLn1sDaeu8+0phgb8kT3GmBDZOykkI3ZO8nMjV2p3MGkJI4K5P+bxR8Ztq0bwsA==",
|
||||
"requires": {
|
||||
"vary": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
assets/dockerfiles/base/node/package.json
vendored
1
assets/dockerfiles/base/node/package.json
vendored
@@ -10,6 +10,7 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@koa/cors": "^2.2.3",
|
||||
"get-port": "^3.2.0",
|
||||
"is-generator-function": "^1.0.6",
|
||||
"koa": "^2.3.0",
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/metrue/fx/constants"
|
||||
containerruntimes "github.com/metrue/fx/container_runtimes"
|
||||
"github.com/metrue/fx/context"
|
||||
"github.com/metrue/fx/hook"
|
||||
"github.com/metrue/fx/packer"
|
||||
"github.com/metrue/fx/pkg/spinner"
|
||||
"github.com/metrue/fx/utils"
|
||||
@@ -39,6 +40,9 @@ func BuildImage(ctx context.Contexter) (err error) {
|
||||
if err := packer.Pack(workdir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
docker := ctx.Get("docker").(containerruntimes.ContainerRuntime)
|
||||
@@ -68,6 +72,9 @@ func ExportImage(ctx context.Contexter) (err error) {
|
||||
if err := packer.Pack(outputDir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(outputDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("exported to %v: %v", outputDir, constants.CheckedSymbol)
|
||||
|
||||
1
hook/.hooks/before_build
Normal file
1
hook/.hooks/before_build
Normal file
@@ -0,0 +1 @@
|
||||
npm install
|
||||
15
hook/fixture/package.json
Normal file
15
hook/fixture/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "fixture",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"leftpad": "0.0.1"
|
||||
}
|
||||
}
|
||||
73
hook/hook.go
Normal file
73
hook/hook.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
// Hooker defines hook interface
|
||||
type Hooker interface {
|
||||
Run() error
|
||||
}
|
||||
|
||||
// Hook to run
|
||||
type Hook struct {
|
||||
name string
|
||||
script string
|
||||
}
|
||||
|
||||
// New a hook
|
||||
func New(name string, script string, workdir string) *Hook {
|
||||
return &Hook{
|
||||
name: name,
|
||||
script: script,
|
||||
}
|
||||
}
|
||||
|
||||
// Run execute a hook
|
||||
func (h *Hook) Run(workdir string) error {
|
||||
var script string
|
||||
if !utils.IsRegularFile(h.script) {
|
||||
hookScript, err := ioutil.TempFile(os.TempDir(), "fx-hook-script-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.Remove(hookScript.Name())
|
||||
|
||||
content := []byte(h.script)
|
||||
if _, err = hookScript.Write(content); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hookScript.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
script = hookScript.Name()
|
||||
} else {
|
||||
absScript, err := filepath.Abs(h.script)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
script = absScript
|
||||
}
|
||||
|
||||
cmd := exec.Command("/bin/sh", script)
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if workdir != "" {
|
||||
cmd.Dir = workdir
|
||||
}
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name hook name
|
||||
func (h *Hook) Name() string {
|
||||
return h.name
|
||||
}
|
||||
54
hook/hook_manager.go
Normal file
54
hook/hook_manager.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
// HookNameBeforeBuild before build hook
|
||||
const HookNameBeforeBuild = "before_build"
|
||||
|
||||
// RunBeforeBuildHook trigger before_build hook
|
||||
func RunBeforeBuildHook(workdir string) error {
|
||||
hooks, err := descovery("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, h := range hooks {
|
||||
if h.Name() == HookNameBeforeBuild {
|
||||
if err := h.Run(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func descovery(hookdir string) ([]*Hook, error) {
|
||||
if hookdir == "" {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hookdir = filepath.Join(dir, ".hooks")
|
||||
}
|
||||
|
||||
hooks := []*Hook{}
|
||||
if !utils.IsDir(hookdir) {
|
||||
return hooks, nil
|
||||
}
|
||||
if err := filepath.Walk(hookdir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Name() == HookNameBeforeBuild {
|
||||
hooks = append(hooks, New("before_build", path, ""))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hooks, nil
|
||||
}
|
||||
40
hook/hook_manager_test.go
Normal file
40
hook/hook_manager_test.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHookManager(t *testing.T) {
|
||||
t.Run("descovery in default hookdir .hooks", func(t *testing.T) {
|
||||
hooks, err := descovery("")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(hooks) != 1 {
|
||||
t.Fatalf("should have one hook, but got %d", len(hooks))
|
||||
}
|
||||
|
||||
if hooks[0].Name() != HookNameBeforeBuild {
|
||||
t.Fatalf("should be before_build hook, but got %s", hooks[0].Name())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("descovery in empty hookdir", func(t *testing.T) {
|
||||
hooks, err := descovery(filepath.Join(os.TempDir(), ".hooks"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(hooks) != 0 {
|
||||
t.Fatalf("should get 0 hooks, but got %d", len(hooks))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("run before_build hook", func(t *testing.T) {
|
||||
if err := RunBeforeBuildHook("fixture"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
21
hook/hook_test.go
Normal file
21
hook/hook_test.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHook(t *testing.T) {
|
||||
t.Run("text", func(t *testing.T) {
|
||||
h := New("before_build", "npm install leftpad", "fixture")
|
||||
if err := h.Run("fixture"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("script", func(t *testing.T) {
|
||||
h := New("before_build", ".hooks/before_build", "fixture")
|
||||
if err := h.Run("fixture"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
containerruntimes "github.com/metrue/fx/container_runtimes"
|
||||
"github.com/metrue/fx/context"
|
||||
"github.com/metrue/fx/hook"
|
||||
"github.com/metrue/fx/packer"
|
||||
"github.com/metrue/fx/pkg/spinner"
|
||||
"github.com/metrue/fx/types"
|
||||
@@ -54,6 +55,9 @@ func Build(ctx context.Contexter) (err error) {
|
||||
if err := packer.Pack(workdir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cloudType := ctx.Get("cloud_type").(string)
|
||||
|
||||
@@ -24,7 +24,7 @@ func init() {
|
||||
packr.PackJSONBytes("./images", "julia/deps.jl", "\"b3BlbigiL2FwcC9SRVFVSVJFIikgZG8gZgoJZGVwcyA9IHJlYWRsaW5lcyhmKQoJZm9yIGQgaW4gZGVwcwoJCVBrZy5hZGQoZCkKCWVuZAplbmQKUGtnLmJ1aWxkKCJIdHRwUGFyc2VyIikK\"")
|
||||
packr.PackJSONBytes("./images", "julia/fx.jl", "\"CnN0cnVjdCBJbnB1dAogICAgYTo6TnVtYmVyCiAgICBiOjpOdW1iZXIKZW5kCgpmeCA9IGZ1bmN0aW9uKGlucHV0OjpJbnB1dCkKICAgIHJldHVybiBpbnB1dC5hICsgaW5wdXQuYgplbmQK\"")
|
||||
packr.PackJSONBytes("./images", "node/Dockerfile", "\"RlJPTSBtZXRydWUvZngtbm9kZS1iYXNlCgpDT1BZIC4gLgpFWFBPU0UgMzAwMApDTUQgWyJub2RlIiwgImFwcC5qcyJdCg==\"")
|
||||
packr.PackJSONBytes("./images", "node/app.js", "\"Y29uc3QgS29hID0gcmVxdWlyZSgna29hJyk7CmNvbnN0IGJvZHlQYXJzZXIgPSByZXF1aXJlKCdrb2EtYm9keXBhcnNlcicpOwpjb25zdCBmeCA9IHJlcXVpcmUoJy4vZngnKTsKCmNvbnN0IGFwcCA9IG5ldyBLb2EoKTsKYXBwLnVzZShib2R5UGFyc2VyKCkpOwphcHAudXNlKGZ4KTsKCmFwcC5saXN0ZW4oMzAwMCk7Cg==\"")
|
||||
packr.PackJSONBytes("./images", "node/app.js", "\"Y29uc3QgS29hID0gcmVxdWlyZSgna29hJyk7CmNvbnN0IGJvZHlQYXJzZXIgPSByZXF1aXJlKCdrb2EtYm9keXBhcnNlcicpOwpjb25zdCBjb3JzID0gcmVxdWlyZSgnQGtvYS9jb3JzJyk7CmNvbnN0IGZ4ID0gcmVxdWlyZSgnLi9meCcpOwoKY29uc3QgYXBwID0gbmV3IEtvYSgpOwphcHAudXNlKGNvcnMoewogIG9yaWdpbjogJyonLAp9KSk7CmFwcC51c2UoYm9keVBhcnNlcigpKTsKYXBwLnVzZShmeCk7CgphcHAubGlzdGVuKDMwMDApOwo=\"")
|
||||
packr.PackJSONBytes("./images", "node/fx.js", "\"bW9kdWxlLmV4cG9ydHMgPSAoY3R4KSA9PiB7CiAgY3R4LmJvZHkgPSAnaGVsbG8gd29ybGQnCn0K\"")
|
||||
packr.PackJSONBytes("./images", "perl/Dockerfile", "\"RlJPTSBtZXRydWUvZngtcGVybC1iYXNlCgpBREQgLiAuCgpFWFBPU0UgMzAwMApDTUQgWyJwZXJsIiwgImFwcC5wbCIsICJkYWVtb24iXQo=\"")
|
||||
packr.PackJSONBytes("./images", "perl/app.pl", "\"dXNlIE1vam9saWNpb3VzOjpMaXRlOwoKcmVxdWlyZSAiLi9meC5wbCI7CgpnZXQgJy8nID0+IHN1YiB7CiAgbXkgJGN0eCA9IHNoaWZ0OwogIG15ICRyZXMgPSBmeCgkY3R4KTsKICAkY3R4LT5yZW5kZXIoanNvbiA9PiAkcmVzKTsKfTsKCnBvc3QgJy8nID0+IHN1YiB7CiAgbXkgJGN0eCA9IHNoaWZ0OwogIG15ICRyZXMgPSBmeCgkY3R4KTsKICAkY3R4LT5yZW5kZXIoanNvbiA9PiAkcmVzKTsKfTsKCmFwcC0+c3RhcnQ7Cg==\"")
|
||||
|
||||
4
packer/images/node/app.js
vendored
4
packer/images/node/app.js
vendored
@@ -1,8 +1,12 @@
|
||||
const Koa = require('koa');
|
||||
const bodyParser = require('koa-bodyparser');
|
||||
const cors = require('@koa/cors');
|
||||
const fx = require('./fx');
|
||||
|
||||
const app = new Koa();
|
||||
app.use(cors({
|
||||
origin: '*',
|
||||
}));
|
||||
app.use(bodyParser());
|
||||
app.use(fx);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user