Skip to content

Commit

Permalink
New input type: Component (#5)
Browse files Browse the repository at this point in the history
- Triggers change when that component changed
- Delays action execution until after input component has completed
  • Loading branch information
kristofferlind authored Nov 27, 2022
1 parent f0e46c7 commit 7f66bce
Show file tree
Hide file tree
Showing 20 changed files with 388 additions and 89 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ install: build
test: build
docker-compose down
docker-compose up -d
KNEGA=../knega KNEGA_TRACE=true KNEGA_ALLOW_INSECURE_REGISTRY=true bats --print-output-on-failure --show-output-of-passing-tests test
KNEGA=../knega KNEGA_TRACE=true KNEGA_ALLOW_INSECURE_REGISTRY=true bats --print-output-on-failure test
docker-compose down

test-release:
Expand Down
4 changes: 2 additions & 2 deletions examples/.knega.root.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
componentPaths: ["components"]
componentSearchDepth: 2
concurrency: 4
componentSearchDepth: 1
concurrency: 8

defaultConfiguration:
inputs:
Expand Down
8 changes: 8 additions & 0 deletions examples/components/base-image/.component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: "base-image"

actions:
build:
commands:
- $ROOT/scripts/build.sh
- docker tag localhost:5000/$COMPONENT_NAME:$INPUTS_HASH localhost:5000/$COMPONENT_NAME:0.1.0
- docker push localhost:5000/$COMPONENT_NAME:0.1.0
1 change: 1 addition & 0 deletions examples/components/base-image/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM alpine
11 changes: 11 additions & 0 deletions examples/components/with-dependency-on-example-1/.component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: "with-dependency-on-example-1"

inputs:
- type: "Files"
paths: ["$ROOT/.knega.root.yml"]
- type: "GitFiles"
paths: ["*"]
- type: "Component"
name: "example-1"
- type: "Component"
name: "base-image"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM localhost:5000/base-image:0.1.0
11 changes: 11 additions & 0 deletions examples/components/with-nested-dependency-1/.component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: "with-nested-dependency-1"

inputs:
- type: "Files"
paths: ["$ROOT/.knega.root.yml"]
- type: "GitFiles"
paths: ["*"]
- type: "Component"
name: "with-dependency-on-example-1"
- type: "Component"
name: "base-image"
1 change: 1 addition & 0 deletions examples/components/with-nested-dependency-1/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FROM localhost:5000/base-image:0.1.0
21 changes: 20 additions & 1 deletion internal/configuration/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Component struct {
Actions map[string]action
InputsHash string
ChangeStatus ChangeStatus
Dependencies []string
}

func initializeComponent(componentPath string, rootConfiguration rootConfiguration, rootPath string) Component {
Expand All @@ -38,8 +39,8 @@ func initializeComponent(componentPath string, rootConfiguration rootConfigurati
component.Inputs = initializeInputs(configuration.Inputs, componentPath, rootPath)
component.Outputs = initializeOutputs(configuration.Outputs)
component.Actions = initializeActions(rootConfiguration.DefaultConfiguration.Actions, configuration.Actions)
component.InputsHash = calculateHash(component.Inputs)
component.ChangeStatus = Unknown
component.Dependencies = getComponentDependencies(configuration.Inputs)

return component
}
Expand All @@ -57,7 +58,20 @@ func initializeComponentConfiguration(componentConfigurationPath string, rootCon
return componentConfiguration
}

func getComponentDependencies(configurationInputs []configurationInput) []string {
var dependencies []string

for _, input := range configurationInputs {
if input.Type == "Component" {
dependencies = append(dependencies, input.Name)
}
}

return dependencies
}

func (component *Component) HasChanges() bool {
component.InputsHash = calculateHash(component.Inputs)
hasChanges := false
component.ChangeStatus = Pristine
variables := map[string]string{
Expand Down Expand Up @@ -85,3 +99,8 @@ func calculateHash(inputs []input) string {

return hex.EncodeToString(checksum)
}

func (component *Component) calculateHash() {
inputsHash := calculateHash(component.Inputs)
component.InputsHash = inputsHash
}
28 changes: 28 additions & 0 deletions internal/configuration/componentInput.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package configuration

import "log"

type componentInput struct {
name string
}

func (input componentInput) Hash() []byte {
repository := GetRepository()
var component Component
found := false
for _, repoComponent := range repository.components {
if repoComponent.Name == input.name {
component = repoComponent
found = true
}
}

if !found {
log.Fatalf("Input component with name %s could not be found", input.name)
}

// just returning inputshash of that component should be enough if resolved in correct order
// return []byte(component.InputsHash)
// for now we'll need to rerun the calculation
return []byte(calculateHash(component.Inputs))
}
1 change: 1 addition & 0 deletions internal/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type rootConfiguration struct {
type configurationInput struct {
Type string `yaml:"type"`
Paths []string `yaml:"paths"`
Name string `yaml:"name"`
}

type configurationOutput struct {
Expand Down
76 changes: 76 additions & 0 deletions internal/configuration/fileInput.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package configuration

import (
"crypto/sha512"
"io"
"log"
"os"
"path/filepath"
"strings"
)

type fileInput struct {
path string
}

func fileInputPatternsToPaths(patterns []string, rootPath string) []string {
var results []string

for _, pattern := range patterns {
pattern = strings.ReplaceAll(pattern, "$ROOT", rootPath)
matches, err := filepath.Glob(pattern)
if err != nil {
log.Fatal(err)
}
results = append(results, matches...)
}
return results
}

func gitFileInputPatternsToPaths(patterns []string, applicationPath string) []string {
var results []string

for _, pattern := range patterns {
matches := gitLsFiles(applicationPath, pattern)
for _, relativePath := range matches {
path := filepath.Join(applicationPath, relativePath)
if isFile(path) {
results = append(results, path)
}
}
}

return results
}

func deDuplicateStringSlice(paths []string) []string {
pathMap := make(map[string]string)
var results []string
for _, path := range paths {
exists := pathMap[path]
if exists == "" {
pathMap[path] = path
results = append(results, path)
}
}

return results
}

func (input fileInput) Hash() []byte {
file, err := os.Open(input.path)
if err != nil {
log.Fatal(err)
}

defer file.Close()

hash := sha512.New384()

_, copyErr := io.Copy(hash, file)
if copyErr != nil {
log.Fatal(copyErr)
}

return hash.Sum(nil)
}
84 changes: 11 additions & 73 deletions internal/configuration/input.go
Original file line number Diff line number Diff line change
@@ -1,65 +1,18 @@
package configuration

import (
"crypto/sha512"
"io"
"log"
"os"
"path/filepath"
"strings"
)

type input struct {
path string
}

func fileInputPatternsToPaths(patterns []string, rootPath string) []string {
var results []string

for _, pattern := range patterns {
pattern = strings.ReplaceAll(pattern, "$ROOT", rootPath)
matches, err := filepath.Glob(pattern)
if err != nil {
log.Fatal(err)
}
results = append(results, matches...)
}
return results
}

func gitFileInputPatternsToPaths(patterns []string, applicationPath string) []string {
var results []string

for _, pattern := range patterns {
matches := gitLsFiles(applicationPath, pattern)
for _, relativePath := range matches {
path := filepath.Join(applicationPath, relativePath)
if isFile(path) {
results = append(results, path)
}
}
}

return results
}

func deDuplicateStringSlice(paths []string) []string {
pathMap := make(map[string]string)
var results []string
for _, path := range paths {
exists := pathMap[path]
if exists == "" {
pathMap[path] = path
results = append(results, path)
}
}

return results
type input interface {
Hash() []byte
}

func initializeInputs(configurationInputs []configurationInput, componentPath string, rootPath string) []input {
var paths []string

var inputs []input

for _, configurationInput := range configurationInputs {
switch configurationInput.Type {
case "Files":
Expand All @@ -68,39 +21,24 @@ func initializeInputs(configurationInputs []configurationInput, componentPath st
case "GitFiles":
filePaths := gitFileInputPatternsToPaths(configurationInput.Paths, componentPath)
paths = append(paths, filePaths...)
case "Component":
componentInput := componentInput{
name: configurationInput.Name,
}
inputs = append(inputs, componentInput)
default:
log.Fatal("One of the input types does not have a handler, check types on handlers")
log.Fatalf("One of the input types does not have a handler, check types on handlers in %s or root config", componentPath)
}
}

uniquePaths := deDuplicateStringSlice(paths)

var inputs []input

for _, path := range uniquePaths {
input := input{
input := fileInput{
path: path,
}
inputs = append(inputs, input)
}

return inputs
}

func (input *input) Hash() []byte {
file, err := os.Open(input.path)
if err != nil {
log.Fatal(err)
}

defer file.Close()

hash := sha512.New384()

_, copyErr := io.Copy(hash, file)
if copyErr != nil {
log.Fatal(copyErr)
}

return hash.Sum(nil)
}
3 changes: 3 additions & 0 deletions internal/configuration/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func (repository *repository) FindComponentsWithAction(action string) []Componen
var components []Component
for _, component := range repository.components {
_, hasProperty := component.Actions[action]
if len(component.InputsHash) == 0 {
component.calculateHash()
}
if hasProperty {
components = append(components, component)
}
Expand Down
Loading

0 comments on commit 7f66bce

Please sign in to comment.