Skip to content

Commit c58c038

Browse files
authored
Merge pull request #2 from jpnt/alpha
Merge Alpha
2 parents f0e89da + c4f50cd commit c58c038

File tree

21 files changed

+168
-65
lines changed

21 files changed

+168
-65
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
TODO.md
2-
kman
2+
kman*
33
*old
44
linux*

README.md

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,61 @@
33
kman aims to automate and unify the Linux Kernel installation from source process, allowing for a
44
repeatable way of installing a Linux kernel, generating a initramfs image and updating
55
the bootloader configuration, based on the tools and configurations available of your system,
6-
offering a sane and powerful way to manage kernels on any Linux distribution.
6+
offering a sane and powerful way to manage kernels in any Linux distribution.
77

8-
## Features
8+
## Installation process
9+
10+
### Via precompiled binaries
11+
12+
1. Go to [releases](https://github.com/jpnt/kman/releases)
13+
14+
2. Download binary for your architecture
15+
16+
3. Make the binary executable
17+
18+
```sh
19+
chmod +x kman-amd64
20+
```
21+
22+
4. Verify installation
23+
24+
```sh
25+
kman -version
26+
```
27+
28+
### Via Go get (for go devs)
29+
30+
```sh
31+
go install github.com/yourrepo/kman@latest
32+
kman --version
33+
```
934

35+
### Build from source
36+
37+
```sh
38+
git clone https://github.com/yourrepo/kman.git && cd kman
39+
go mod tidy # install deps
40+
go build -o kman ./cmd/kman
41+
kman --version
42+
```
43+
44+
## Examples
45+
46+
- Run everything (download, compile, install, etc)
47+
48+
```sh
49+
$ kman run-all
50+
```
51+
52+
- Run a specific step(s)
53+
54+
TODO: is it possible to simplify even further?
55+
56+
```sh
57+
$ kman install,bootloader,initramfs --dir=./kernel-6.9.9 --initramfs=booster
58+
```
59+
60+
## Features
1061

1162
- [x] Minimal external libraries
1263
- [x] Cross‑distro compatibility

cmd/kman/kman.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,16 @@ import (
99
)
1010

1111
func main() {
12-
l := logger.NewLogger(logger.InfoLevel)
13-
12+
log := logger.NewLogger(logger.InfoLevel)
1413
ctx := core.NewKernelContext()
15-
p := core.NewPipeline(ctx)
16-
f := service.NewStepFactory()
17-
18-
b := core.NewPipelineBuilder(l, p, f)
14+
factory := service.NewStepFactory()
15+
builder := core.NewPipelineBuilder(log, factory, ctx)
1916

20-
b = b.WithDefault()
21-
// TODO: dynamic argument builder configuration
17+
pipeline := builder.WithDefault().Build()
2218

23-
err := p.Run()
19+
err := pipeline.Run()
2420
if err != nil {
25-
l.Error("Error: %s", err.Error())
21+
log.Error("%s", err.Error())
2622
os.Exit(1)
2723
}
2824
}

internal/core/pipeline.go

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,50 @@ package core
22

33
import (
44
"fmt"
5+
"time"
6+
7+
"github.com/jpnt/kman/pkg/logger"
58
)
69

710
type IPipeline interface {
8-
AddStep(step IStep)
9-
Steps() []IStep
10-
Ctx() IKernelContext
1111
Run() error
1212
}
1313

1414
type Pipeline struct {
15+
log logger.ILogger
1516
steps []IStep
1617
ctx IKernelContext
1718
}
1819

1920
// Ensure struct implements interface
2021
var _ IPipeline = (*Pipeline)(nil)
2122

22-
func NewPipeline(c IKernelContext) *Pipeline {
23-
return &Pipeline{ctx: c}
24-
}
25-
26-
func (pl *Pipeline) AddStep(step IStep) {
27-
pl.steps = append(pl.steps, step)
28-
}
29-
30-
func (pl *Pipeline) Steps() []IStep {
31-
return pl.steps
32-
}
33-
34-
func (pl *Pipeline) Ctx() IKernelContext {
35-
return pl.ctx
36-
}
37-
3823
func (pl *Pipeline) Run() error {
39-
if len(pl.Steps()) == 0 {
24+
if len(pl.steps) == 0 {
4025
return fmt.Errorf("no steps were configured")
4126
}
4227

28+
pl.log.Info("The following steps will be executed:")
4329
for _, step := range pl.steps {
30+
pl.log.Info("- %s", step.Name())
31+
}
32+
33+
pl.log.Info("Starting execution ...")
34+
35+
for _, step := range pl.steps {
36+
start := time.Now()
37+
pl.log.Info("==> Starting step: %s ...", step.Name())
38+
4439
if err := pl.ctx.Validate(step.Name()); err != nil {
4540
return fmt.Errorf("validation failed for step %q: %w", step.Name(), err)
4641
}
4742

4843
if err := step.Execute(); err != nil {
4944
return fmt.Errorf("execution failed for step %q: %w", step.Name(), err)
5045
}
46+
47+
duration := time.Since(start)
48+
pl.log.Info("<== Completed step: %s in %s", step.Name(), duration)
5149
}
5250
return nil
5351
}

internal/core/pipeline_builder.go

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,52 @@
11
package core
22

3+
// https://refactoring.guru/design-patterns/builder
4+
35
import (
46
"github.com/jpnt/kman/pkg/logger"
57
)
68

79
type IPipelineBuilder interface {
810
WithStep(stepName string) IPipelineBuilder
911
WithDefault() IPipelineBuilder
12+
Build() IPipeline
1013
}
1114

1215
type PipelineBuilder struct {
1316
logger logger.ILogger
14-
pl IPipeline
1517
factory IStepFactory
18+
ctx IKernelContext
19+
steps []IStep
1620
}
1721

1822
// Ensure struct implements interface
1923
var _ IPipelineBuilder = (*PipelineBuilder)(nil)
2024

21-
func NewPipelineBuilder(l logger.ILogger, p IPipeline, f IStepFactory) IPipelineBuilder {
22-
return &PipelineBuilder{logger: l, pl: p, factory: f}
25+
func NewPipelineBuilder(l logger.ILogger, f IStepFactory, c IKernelContext) IPipelineBuilder {
26+
return &PipelineBuilder{logger: l, factory: f, ctx: c}
2327
}
2428

2529
func (b *PipelineBuilder) WithStep(stepName string) IPipelineBuilder {
26-
step, err := b.factory.CreateStep(stepName, b.logger, b.pl.Ctx())
30+
step, err := b.factory.CreateStep(stepName, b.logger, b.ctx)
2731
if err != nil {
28-
b.logger.Warn("Unrecognized step: %q", stepName)
32+
b.logger.Warn("Failed to create step %s: %s", stepName, err)
2933
return b
3034
}
31-
b.pl.AddStep(step)
35+
b.steps = append(b.steps, step)
36+
3237
return b
3338
}
3439

3540
func (b *PipelineBuilder) WithDefault() IPipelineBuilder {
36-
return b.
37-
WithStep("list").
38-
WithStep("download").
39-
WithStep("verify").
40-
WithStep("extract").
41-
WithStep("patch").
42-
WithStep("configure").
43-
WithStep("compile").
44-
WithStep("install").
45-
WithStep("initramfs").
46-
WithStep("bootloader")
41+
availableSteps := b.factory.AvailableSteps()
42+
43+
for _, stepName := range availableSteps {
44+
b.WithStep(stepName)
45+
}
46+
47+
return b
48+
}
49+
50+
func (b *PipelineBuilder) Build() IPipeline {
51+
return &Pipeline{log: b.logger, ctx: b.ctx, steps: b.steps}
4752
}

internal/core/step.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ package core
22

33
type IStep interface {
44
Name() string
5-
// CtxParamsNeeded() []string // TODO: simpler way?
5+
// NeedParams() []string // TODO: simpler way?
6+
// This serves for the use case of when I only want
7+
// to run a set of steps. And for those steps if I have
8+
// not defined the required kernel context parameters
9+
// then it should warn the users. Speficy in the command
10+
// line arguments or prompt the user? What is more suckless
611
Execute() error
7-
// Completed() bool
812
}

internal/core/step_factory.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ import (
55
)
66

77
type IStepFactory interface {
8-
CreateStep(name string, logger logger.ILogger, ctx IKernelContext) (IStep, error)
8+
AvailableSteps() []string
9+
CreateStep(name string, log logger.ILogger, ctx IKernelContext) (IStep, error)
910
}

internal/gateway/bootloader/bootloader.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

internal/gateway/cli/cli.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package cli

0 commit comments

Comments
 (0)