Skip to content

Commit 996f34d

Browse files
committed
buildinfo and artifacts (#93)
* pack exports * basic store implementation *artifact tests * reestablish use of input hash instead of taskname * rewrite hashes to buildinfo * assure artifact rebuild works as intended
1 parent 64057f4 commit 996f34d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1602
-736
lines changed

architecture.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# bob architecture
2+
Fine grained infos on bob's features
3+
4+
5+
## Buildinfo & Artifact Store
6+
Bob uses buildinfos and artifacts store to determine if a rebuild is required or if a target could be loaded from the artifact store.
7+
8+
* check if input hash exists in buildinfo store
9+
* check validity of tragets
10+
* check if tragets can be loaded from artifact store
11+
* rebuild
12+
* write buildinfo
13+
* write artifacts
14+
15+
```
16+
@startuml
17+
ditaa(scale=0.9)
18+
19+
/--------------------------------\
20+
|cFFF |
21+
| `bob build mytask` |
22+
\----+----------------------+----/
23+
| |
24+
| |
25+
| |
26+
/----+-----------------+---------+ /----+---------------------------+
27+
|cFFF | |cFFF |
28+
| buildinfo store | | artifact store |
29+
\--------------------------------/ \--------------------------------/
30+
31+
@enduml
32+
```
33+
34+
#### Buildinfo
35+
A buildinfo item holds general information about the task triggered that build. It also contains a map of input:target combinations for each target in the build chain (child tragets included).
36+
This allows to validate the integraty and existent of all targets.
37+
38+
It can be accessed by the input hash of a task.
39+
40+
#### Artifact
41+
A artifact stores the targets and the path information of a task.
42+
43+
Artifacts can be accesed by the input hash of a task.

bob/aggregate.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ func (b *B) Aggregate() (aggregate *bobfile.Bobfile, err error) {
4747
for variable, value := range boblet.Variables {
4848
for key, task := range boblet.Tasks {
4949
// TODO: Create and use envvar sanitizer
50+
5051
task.AddEnvironment(strings.ToUpper(variable), value)
52+
5153
boblet.Tasks[key] = task
5254
}
5355
}
@@ -117,6 +119,8 @@ func (b *B) Aggregate() (aggregate *bobfile.Bobfile, err error) {
117119
}
118120
}
119121

122+
// TODO: Gather missing tasks from remote & Unpack?
123+
120124
// Gather environment from dependent tasks.
121125
//
122126
// Each export is translated into environment variables named:
@@ -125,6 +129,10 @@ func (b *B) Aggregate() (aggregate *bobfile.Bobfile, err error) {
125129
//
126130
// The file is prefixed with all paths to make it relative to dir of the the top Bobfile:
127131
// `openapi.yaml => sencond-level/openapi.yaml`
132+
//
133+
// TODO: Exports should be part of a packed file and should be evaluated when running a playbook or at least after Unpack().
134+
// Looks like this is the wrong place to presume that all child tasks are comming from child bobfiles
135+
// must exist.
128136
for i, task := range aggregate.Tasks {
129137

130138
for _, dependentTaskName := range task.DependsOn {
@@ -157,6 +165,13 @@ func (b *B) Aggregate() (aggregate *bobfile.Bobfile, err error) {
157165
}
158166
}
159167

168+
// Assure tasks are correctly initialised.
169+
for i, task := range aggregate.Tasks {
170+
task.WithLocalstore(b.local)
171+
task.WithBuildinfoStore(b.buildInfoStore)
172+
aggregate.Tasks[i] = task
173+
}
174+
160175
return aggregate, aggregate.Verify()
161176
}
162177

bob/bob.go

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88

99
"github.com/Benchkram/errz"
1010

11+
"github.com/Benchkram/bob/pkg/buildinfostore"
1112
"github.com/Benchkram/bob/pkg/file"
13+
"github.com/Benchkram/bob/pkg/store"
1214
)
1315

1416
type B struct {
@@ -22,28 +24,55 @@ type B struct {
2224
// dir is bob's working directory.
2325
dir string
2426

27+
// local the place to store artifacts localy
28+
local store.Store
29+
// TODO: add a remote store
30+
// remotestore cas.Store
31+
32+
buildInfoStore buildinfostore.Store
33+
2534
// readConfig some commands need a fully initialised bob.
2635
// When this is true a `.bob/config` file must exist,
2736
// usually done by calling `bob init`
2837
readConfig bool
2938
}
3039

31-
func new() *B {
40+
func new(opts ...Option) *B {
3241
wd, err := os.Getwd()
3342
if err != nil {
3443
errz.Fatal(err)
3544
}
3645

37-
c := &B{
46+
b := &B{
3847
DefaultCloneSchema: SSH,
48+
dir: wd,
49+
}
3950

40-
dir: wd,
51+
for _, opt := range opts {
52+
if opt == nil {
53+
continue
54+
}
55+
opt(b)
4156
}
42-
return c
57+
58+
return b
4359
}
4460

45-
func Bob(opts ...Option) (*B, error) {
46-
bob := new()
61+
// BobWithBaseStoreDir initialises stores in the given directory
62+
func BobWithBaseStoreDir(baseStoreDir string, opts ...Option) (*B, error) {
63+
bob := new(opts...)
64+
65+
fs, err := Filestore(baseStoreDir)
66+
if err != nil {
67+
return nil, err
68+
}
69+
bob.local = fs
70+
71+
bis, err := BuildinfoStore(baseStoreDir)
72+
if err != nil {
73+
return nil, err
74+
}
75+
bob.buildInfoStore = bis
4776

4877
for _, opt := range opts {
4978
if opt == nil {
@@ -52,13 +81,35 @@ func Bob(opts ...Option) (*B, error) {
5281
opt(bob)
5382
}
5483

84+
return bob, nil
85+
}
86+
87+
func Bob(opts ...Option) (*B, error) {
88+
bob := new(opts...)
89+
5590
if bob.readConfig {
5691
err := bob.read()
5792
if err != nil {
5893
return nil, err
5994
}
6095
}
6196

97+
if bob.local == nil {
98+
fs, err := DefaultFilestore()
99+
if err != nil {
100+
return nil, err
101+
}
102+
bob.local = fs
103+
}
104+
105+
if bob.buildInfoStore == nil {
106+
bis, err := DefaultBuildinfoStore()
107+
if err != nil {
108+
return nil, err
109+
}
110+
bob.buildInfoStore = bis
111+
}
112+
62113
return bob, nil
63114
}
64115

bob/bob_stores.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package bob
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
7+
"github.com/Benchkram/bob/bob/global"
8+
"github.com/Benchkram/bob/pkg/buildinfostore"
9+
"github.com/Benchkram/bob/pkg/store"
10+
"github.com/Benchkram/bob/pkg/store/filestore"
11+
"github.com/Benchkram/errz"
12+
)
13+
14+
func DefaultFilestore() (s store.Store, err error) {
15+
defer errz.Recover(&err)
16+
17+
home, err := os.UserHomeDir()
18+
errz.Fatal(err)
19+
20+
storeDir := filepath.Join(home, global.BobCacheArtifactsDir)
21+
err = os.MkdirAll(storeDir, 0775)
22+
errz.Fatal(err)
23+
24+
return filestore.New(storeDir), nil
25+
}
26+
27+
func Filestore(dir string) (s store.Store, err error) {
28+
defer errz.Recover(&err)
29+
30+
storeDir := filepath.Join(dir, global.BobCacheArtifactsDir)
31+
err = os.MkdirAll(storeDir, 0775)
32+
errz.Fatal(err)
33+
34+
return filestore.New(storeDir), nil
35+
}
36+
37+
func MustDefaultFilestore() store.Store {
38+
s, _ := DefaultFilestore()
39+
return s
40+
}
41+
42+
func DefaultBuildinfoStore() (s buildinfostore.Store, err error) {
43+
defer errz.Recover(&err)
44+
45+
home, err := os.UserHomeDir()
46+
errz.Fatal(err)
47+
48+
storeDir := filepath.Join(home, global.BobCacheBuildinfoDir)
49+
err = os.MkdirAll(storeDir, 0775)
50+
errz.Fatal(err)
51+
52+
return buildinfostore.New(storeDir), nil
53+
}
54+
55+
func BuildinfoStore(dir string) (s buildinfostore.Store, err error) {
56+
defer errz.Recover(&err)
57+
58+
storeDir := filepath.Join(dir, global.BobCacheBuildinfoDir)
59+
err = os.MkdirAll(storeDir, 0775)
60+
errz.Fatal(err)
61+
62+
return buildinfostore.New(storeDir), nil
63+
}
64+
65+
func MustDefaultBuildinfoStore() buildinfostore.Store {
66+
s, _ := DefaultBuildinfoStore()
67+
return s
68+
}

bob/bobfile/bobfile.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,9 @@ func bobfileRead(dir string) (_ *Bobfile, err error) {
8484

8585
// Make sure a task is correctly initialised.
8686
// TODO: All unitialised must be initialised or get default values.
87-
// This mean switching to pointer types for most members.
87+
// This means switching to pointer types for most members.
8888
task.SetEnv([]string{})
8989

90-
// if task.TargetDirty.Type == "" {
91-
// task.T
92-
// }
93-
9490
bobfile.Tasks[key] = task
9591
}
9692

bob/bobfile/playbook.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ import (
66
)
77

88
func (b *Bobfile) Playbook(taskname string) (*playbook.Playbook, error) {
9-
pb := playbook.New(taskname)
9+
pb := playbook.New(
10+
taskname,
11+
)
12+
1013
err := b.Tasks.Walk(taskname, "", func(tn string, task bobtask.Task, err error) error {
1114
if err != nil {
1215
return err

bob/build.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ var (
1111
ErrNoRebuildRequired = errors.New("no rebuild required")
1212
)
1313

14+
// Build a task and it's dependecies.
1415
func (b *B) Build(ctx context.Context, taskname string) (err error) {
1516
defer errz.Recover(&err)
1617

bob/builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ var _ ctl.Builder = (*builder)(nil)
1111

1212
type BuildFunc func(_ context.Context, runname string, aggregate *bobfile.Bobfile) error
1313

14-
// builder holds all dependecys to build a build task
14+
// builder holds all dependencys to build a build task
1515
type builder struct {
1616
task string
1717
aggregate *bobfile.Bobfile

bob/clean.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package bob
2+
3+
func (b B) Clean() error {
4+
return b.cleanBuildInfoStore()
5+
}
6+
7+
func (b B) cleanBuildInfoStore() error {
8+
return b.buildInfoStore.Clean()
9+
}

bob/global/global.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ package global
33
import "path/filepath"
44

55
const (
6-
BobCacheDir = ".bobcache"
76
BobFileName = "bob.yaml"
87
BuildToolDir = ".bob"
98
ConfigFile = "config"
109
DefaultBuildTask = "build"
1110
)
1211

12+
// Cache directory
13+
const BobCacheDir = ".bobcache"
14+
1315
var (
14-
FileHashesFileName = filepath.Join(BobCacheDir, "filehashes")
15-
TaskHashesFileName = filepath.Join(BobCacheDir, "hashes")
16+
BobCacheBuildinfoDir = filepath.Join(BobCacheDir, "buildinfos")
17+
BobCacheTaskHashesFileName = filepath.Join(BobCacheDir, "hashes")
18+
BobCacheArtifactsDir = filepath.Join(BobCacheDir, "artifacts")
1619
)

bob/options.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package bob
22

3+
import (
4+
"github.com/Benchkram/bob/pkg/buildinfostore"
5+
"github.com/Benchkram/bob/pkg/store"
6+
)
7+
38
type Option func(b *B)
49

510
func WithDir(dir string) Option {
@@ -15,3 +20,15 @@ func WithRequireBobConfig() Option {
1520
b.readConfig = true
1621
}
1722
}
23+
24+
func WithFilestore(store store.Store) Option {
25+
return func(b *B) {
26+
b.local = store
27+
}
28+
}
29+
30+
func WithBuildinfoStore(store buildinfostore.Store) Option {
31+
return func(b *B) {
32+
b.buildInfoStore = store
33+
}
34+
}

0 commit comments

Comments
 (0)