mirror of
https://github.com/mudler/luet.git
synced 2025-09-06 17:50:34 +00:00
Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6f623ae016 | ||
|
bd80f9acd2 | ||
|
045d25bb28 | ||
|
908b6d2bd4 | ||
|
a3ada624a7 | ||
|
09c7609a7f | ||
|
a1acab0e52 | ||
|
93187182e5 | ||
|
5e7cd183be | ||
|
9c0f0e3457 | ||
|
1120b1ee59 | ||
|
4010033e0c | ||
|
a076613f66 | ||
|
c184b4b3bc | ||
|
40d1f1785b | ||
|
11944f4b8c | ||
|
6f41f8bd8d | ||
|
95b125cb91 |
23
.github/workflows/release.yml
vendored
Normal file
23
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
on: push
|
||||||
|
name: Build and release on push
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Test and Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.14.x
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Tests
|
||||||
|
run: sudo -E env "PATH=$PATH" make deps multiarch-build test-integration test-coverage
|
||||||
|
- name: Build
|
||||||
|
run: sudo -E env "PATH=$PATH" make multiarch-build && sudo chmod -R 777 release/
|
||||||
|
- name: Release
|
||||||
|
uses: fnkr/github-action-ghr@v1
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
env:
|
||||||
|
GHR_PATH: release/
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
21
.github/workflows/test.yml
vendored
Normal file
21
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
on: pull_request
|
||||||
|
name: Build and Test
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.14.x]
|
||||||
|
platform: [ubuntu-latest]
|
||||||
|
runs-on: ${{ matrix.platform }}
|
||||||
|
steps:
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: ${{ matrix.go-version }}
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: setup-docker
|
||||||
|
uses: docker-practice/actions-setup-docker@0.0.1
|
||||||
|
- name: Tests
|
||||||
|
run: sudo -E env "PATH=$PATH" make deps multiarch-build test-integration test-coverage
|
14
.travis.yml
14
.travis.yml
@@ -10,10 +10,10 @@ before_install:
|
|||||||
- sudo -E env "PATH=$PATH" make deps
|
- sudo -E env "PATH=$PATH" make deps
|
||||||
script:
|
script:
|
||||||
- sudo -E env "PATH=$PATH" make multiarch-build test-integration test-coverage
|
- sudo -E env "PATH=$PATH" make multiarch-build test-integration test-coverage
|
||||||
after_success:
|
#after_success:
|
||||||
- |
|
# - |
|
||||||
if [ -n "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
|
# if [ -n "$TRAVIS_TAG" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
|
||||||
sudo -E env "PATH=$PATH" git config --global user.name "Deployer" && git config --global user.email foo@bar.com
|
# sudo -E env "PATH=$PATH" git config --global user.name "Deployer" && git config --global user.email foo@bar.com
|
||||||
sudo -E env "PATH=$PATH" go get github.com/tcnksm/ghr
|
# sudo -E env "PATH=$PATH" go get github.com/tcnksm/ghr
|
||||||
sudo -E env "PATH=$PATH" ghr -u mudler -r luet --replace $TRAVIS_TAG release/
|
# sudo -E env "PATH=$PATH" ghr -u mudler -r luet --replace $TRAVIS_TAG release/
|
||||||
fi
|
# fi
|
||||||
|
@@ -38,7 +38,7 @@ var Verbose bool
|
|||||||
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
var LockedCommands = []string{"install", "uninstall", "upgrade"}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LuetCLIVersion = "0.8.4"
|
LuetCLIVersion = "0.8.5"
|
||||||
LuetEnvPrefix = "LUET"
|
LuetEnvPrefix = "LUET"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -18,12 +18,11 @@ package cmd_tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
//"os"
|
|
||||||
//"sort"
|
|
||||||
|
|
||||||
. "github.com/mudler/luet/pkg/logger"
|
. "github.com/mudler/luet/pkg/logger"
|
||||||
spectooling "github.com/mudler/luet/pkg/spectooling"
|
spectooling "github.com/mudler/luet/pkg/spectooling"
|
||||||
tree "github.com/mudler/luet/pkg/tree"
|
tree "github.com/mudler/luet/pkg/tree"
|
||||||
|
version "github.com/mudler/luet/pkg/versioner"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -43,17 +42,26 @@ func NewTreeBumpCommand() *cobra.Command {
|
|||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
spec, _ := cmd.Flags().GetString("definition-file")
|
spec, _ := cmd.Flags().GetString("definition-file")
|
||||||
toStdout, _ := cmd.Flags().GetBool("to-stdout")
|
toStdout, _ := cmd.Flags().GetBool("to-stdout")
|
||||||
|
pkgVersion, _ := cmd.Flags().GetString("pkg-version")
|
||||||
pack, err := tree.ReadDefinitionFile(spec)
|
pack, err := tree.ReadDefinitionFile(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal(err.Error())
|
Fatal(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pkgVersion != "" {
|
||||||
|
validator := &version.WrappedVersioner{}
|
||||||
|
err := validator.Validate(pkgVersion)
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Invalid version string: " + err.Error())
|
||||||
|
}
|
||||||
|
pack.SetVersion(pkgVersion)
|
||||||
|
} else {
|
||||||
// Retrieve version build section with Gentoo parser
|
// Retrieve version build section with Gentoo parser
|
||||||
err = pack.BumpBuildVersion()
|
err = pack.BumpBuildVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Fatal("Error on increment build version: " + err.Error())
|
Fatal("Error on increment build version: " + err.Error())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if toStdout {
|
if toStdout {
|
||||||
data, err := spectooling.NewDefaultPackageSanitized(&pack).Yaml()
|
data, err := spectooling.NewDefaultPackageSanitized(&pack).Yaml()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -72,6 +80,7 @@ func NewTreeBumpCommand() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ans.Flags().StringP("pkg-version", "p", "", "Set a specific package version")
|
||||||
ans.Flags().StringP("definition-file", "f", "", "Path of the definition to bump.")
|
ans.Flags().StringP("definition-file", "f", "", "Path of the definition to bump.")
|
||||||
ans.Flags().BoolP("to-stdout", "o", false, "Bump package to output.")
|
ans.Flags().BoolP("to-stdout", "o", false, "Bump package to output.")
|
||||||
|
|
||||||
|
@@ -35,36 +35,61 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateWorker(i int,
|
type ValidateOpts struct {
|
||||||
wg *sync.WaitGroup,
|
WithSolver bool
|
||||||
c <-chan pkg.Package,
|
OnlyRuntime bool
|
||||||
reciper tree.Builder,
|
OnlyBuildtime bool
|
||||||
withSolver bool,
|
RegExcludes []*regexp.Regexp
|
||||||
regExcludes, regMatches []*regexp.Regexp,
|
RegMatches []*regexp.Regexp
|
||||||
excludes, matches []string,
|
Excludes []string
|
||||||
errs chan error) {
|
Matches []string
|
||||||
|
|
||||||
defer wg.Done()
|
// Runtime validate stuff
|
||||||
|
RuntimeCacheDeps *pkg.InMemoryDatabase
|
||||||
|
RuntimeReciper *tree.InstallerRecipe
|
||||||
|
|
||||||
|
// Buildtime validate stuff
|
||||||
|
BuildtimeCacheDeps *pkg.InMemoryDatabase
|
||||||
|
BuildtimeReciper *tree.CompilerRecipe
|
||||||
|
|
||||||
|
Mutex sync.Mutex
|
||||||
|
BrokenPkgs int
|
||||||
|
BrokenDeps int
|
||||||
|
|
||||||
|
Errors []error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ValidateOpts) IncrBrokenPkgs() {
|
||||||
|
o.Mutex.Lock()
|
||||||
|
defer o.Mutex.Unlock()
|
||||||
|
o.BrokenPkgs++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ValidateOpts) IncrBrokenDeps() {
|
||||||
|
o.Mutex.Lock()
|
||||||
|
defer o.Mutex.Unlock()
|
||||||
|
o.BrokenDeps++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *ValidateOpts) AddError(err error) {
|
||||||
|
o.Mutex.Lock()
|
||||||
|
defer o.Mutex.Unlock()
|
||||||
|
o.Errors = append(o.Errors, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func validatePackage(p pkg.Package, checkType string, opts *ValidateOpts, reciper tree.Builder, cacheDeps *pkg.InMemoryDatabase) error {
|
||||||
|
var errstr string
|
||||||
|
var ans error
|
||||||
|
|
||||||
var depSolver solver.PackageSolver
|
var depSolver solver.PackageSolver
|
||||||
var cacheDeps *pkg.InMemoryDatabase
|
|
||||||
brokenPkgs := 0
|
|
||||||
brokenDeps := 0
|
|
||||||
var errstr string
|
|
||||||
|
|
||||||
|
if opts.WithSolver {
|
||||||
emptyInstallationDb := pkg.NewInMemoryDatabase(false)
|
emptyInstallationDb := pkg.NewInMemoryDatabase(false)
|
||||||
if withSolver {
|
|
||||||
depSolver = solver.NewSolver(pkg.NewInMemoryDatabase(false),
|
depSolver = solver.NewSolver(pkg.NewInMemoryDatabase(false),
|
||||||
reciper.GetDatabase(),
|
reciper.GetDatabase(),
|
||||||
emptyInstallationDb)
|
emptyInstallationDb)
|
||||||
|
|
||||||
// Use Singleton in memory cache for speedup dependencies
|
|
||||||
// analysis
|
|
||||||
cacheDeps = pkg.NewInMemoryDatabase(true).(*pkg.InMemoryDatabase)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for p := range c {
|
|
||||||
|
|
||||||
found, err := reciper.GetDatabase().FindPackages(
|
found, err := reciper.GetDatabase().FindPackages(
|
||||||
&pkg.DefaultPackage{
|
&pkg.DefaultPackage{
|
||||||
Name: p.GetName(),
|
Name: p.GetName(),
|
||||||
@@ -79,28 +104,50 @@ func validateWorker(i int,
|
|||||||
} else {
|
} else {
|
||||||
errstr = "No packages"
|
errstr = "No packages"
|
||||||
}
|
}
|
||||||
Error(fmt.Sprintf("%s/%s-%s: Broken. No versions could be found by database %s",
|
Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken. No versions could be found by database %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
errstr,
|
errstr,
|
||||||
))
|
))
|
||||||
|
|
||||||
errs <- errors.New(
|
opts.IncrBrokenDeps()
|
||||||
fmt.Sprintf("%s/%s-%s: Broken. No versions could be found by database %s",
|
|
||||||
|
return errors.New(
|
||||||
|
fmt.Sprintf("[%9s] %s/%s-%s: Broken. No versions could be found by database %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
errstr,
|
errstr,
|
||||||
))
|
))
|
||||||
|
|
||||||
brokenPkgs++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that we use the right package from right recipier for deps
|
||||||
|
pReciper, err := reciper.GetDatabase().FindPackage(
|
||||||
|
&pkg.DefaultPackage{
|
||||||
|
Name: p.GetName(),
|
||||||
|
Category: p.GetCategory(),
|
||||||
|
Version: p.GetVersion(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
errstr = fmt.Sprintf("[%9s] %s/%s-%s: Error on retrieve package - %s.",
|
||||||
|
checkType,
|
||||||
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
Error(errstr)
|
||||||
|
|
||||||
|
return errors.New(errstr)
|
||||||
|
}
|
||||||
|
p = pReciper
|
||||||
|
|
||||||
pkgstr := fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(),
|
pkgstr := fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(),
|
||||||
p.GetVersion())
|
p.GetVersion())
|
||||||
|
|
||||||
validpkg := true
|
validpkg := true
|
||||||
|
|
||||||
if len(matches) > 0 {
|
if len(opts.Matches) > 0 {
|
||||||
matched := false
|
matched := false
|
||||||
for _, rgx := range regMatches {
|
for _, rgx := range opts.RegMatches {
|
||||||
if rgx.MatchString(pkgstr) {
|
if rgx.MatchString(pkgstr) {
|
||||||
matched = true
|
matched = true
|
||||||
break
|
break
|
||||||
@@ -108,13 +155,13 @@ func validateWorker(i int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !matched {
|
if !matched {
|
||||||
continue
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(excludes) > 0 {
|
if len(opts.Excludes) > 0 {
|
||||||
excluded := false
|
excluded := false
|
||||||
for _, rgx := range regExcludes {
|
for _, rgx := range opts.RegExcludes {
|
||||||
if rgx.MatchString(pkgstr) {
|
if rgx.MatchString(pkgstr) {
|
||||||
excluded = true
|
excluded = true
|
||||||
break
|
break
|
||||||
@@ -122,11 +169,11 @@ func validateWorker(i int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if excluded {
|
if excluded {
|
||||||
continue
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Info("Checking package "+
|
Info(fmt.Sprintf("[%9s] Checking package ", checkType)+
|
||||||
fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(), p.GetVersion()),
|
fmt.Sprintf("%s/%s-%s", p.GetCategory(), p.GetName(), p.GetVersion()),
|
||||||
"with", len(p.GetRequires()), "dependencies and", len(p.GetConflicts()), "conflicts.")
|
"with", len(p.GetRequires()), "dependencies and", len(p.GetConflicts()), "conflicts.")
|
||||||
|
|
||||||
@@ -154,30 +201,33 @@ func validateWorker(i int,
|
|||||||
} else {
|
} else {
|
||||||
errstr = "No packages"
|
errstr = "No packages"
|
||||||
}
|
}
|
||||||
Error(fmt.Sprintf("%s/%s-%s: Broken Dep %s/%s-%s - %s",
|
Error(fmt.Sprintf("[%9s] %s/%s-%s: Broken Dep %s/%s-%s - %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
r.GetCategory(), r.GetName(), r.GetVersion(),
|
r.GetCategory(), r.GetName(), r.GetVersion(),
|
||||||
errstr,
|
errstr,
|
||||||
))
|
))
|
||||||
|
|
||||||
errs <- errors.New(
|
opts.IncrBrokenDeps()
|
||||||
fmt.Sprintf("%s/%s-%s: Broken Dep %s/%s-%s - %s",
|
|
||||||
|
ans = errors.New(
|
||||||
|
fmt.Sprintf("[%9s] %s/%s-%s: Broken Dep %s/%s-%s - %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
r.GetCategory(), r.GetName(), r.GetVersion(),
|
r.GetCategory(), r.GetName(), r.GetVersion(),
|
||||||
errstr))
|
errstr))
|
||||||
|
|
||||||
brokenDeps++
|
|
||||||
|
|
||||||
validpkg = false
|
validpkg = false
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
Debug("Find packages for dep",
|
Debug(fmt.Sprintf("[%9s] Find packages for dep", checkType),
|
||||||
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
|
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
|
||||||
|
|
||||||
if withSolver {
|
if opts.WithSolver {
|
||||||
|
|
||||||
Info(fmt.Sprintf(" :soap: [%2d/%2d] %s/%s-%s: %s/%s-%s",
|
Info(fmt.Sprintf("[%9s] :soap: [%2d/%2d] %s/%s-%s: %s/%s-%s",
|
||||||
|
checkType,
|
||||||
idx+1, len(all),
|
idx+1, len(all),
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
r.GetCategory(), r.GetName(), r.GetVersion(),
|
r.GetCategory(), r.GetName(), r.GetVersion(),
|
||||||
@@ -186,7 +236,7 @@ func validateWorker(i int,
|
|||||||
// Check if the solver is already been done for the deep
|
// Check if the solver is already been done for the deep
|
||||||
_, err := cacheDeps.Get(r.HashFingerprint(""))
|
_, err := cacheDeps.Get(r.HashFingerprint(""))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
Debug(" :direct_hit: Cache Hit for dep",
|
Debug(fmt.Sprintf("[%9s] :direct_hit: Cache Hit for dep", checkType),
|
||||||
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
|
fmt.Sprintf("%s/%s-%s", r.GetCategory(), r.GetName(), r.GetVersion()))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -201,19 +251,21 @@ func validateWorker(i int,
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
Error(fmt.Sprintf("%s/%s-%s: solver broken for dep %s/%s-%s - %s",
|
Error(fmt.Sprintf("[%9s] %s/%s-%s: solver broken for dep %s/%s-%s - %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
r.GetCategory(), r.GetName(), r.GetVersion(),
|
r.GetCategory(), r.GetName(), r.GetVersion(),
|
||||||
err.Error(),
|
err.Error(),
|
||||||
))
|
))
|
||||||
|
|
||||||
errs <- errors.New(
|
ans = errors.New(
|
||||||
fmt.Sprintf("%s/%s-%s: solver broken for Dep %s/%s-%s - %s",
|
fmt.Sprintf("[%9s] %s/%s-%s: solver broken for Dep %s/%s-%s - %s",
|
||||||
|
checkType,
|
||||||
p.GetCategory(), p.GetName(), p.GetVersion(),
|
p.GetCategory(), p.GetName(), p.GetVersion(),
|
||||||
r.GetCategory(), r.GetName(), r.GetVersion(),
|
r.GetCategory(), r.GetName(), r.GetVersion(),
|
||||||
err.Error()))
|
err.Error()))
|
||||||
|
|
||||||
brokenDeps++
|
opts.IncrBrokenDeps()
|
||||||
validpkg = false
|
validpkg = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,57 +278,155 @@ func validateWorker(i int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !validpkg {
|
if !validpkg {
|
||||||
brokenPkgs++
|
opts.IncrBrokenPkgs()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateWorker(i int,
|
||||||
|
wg *sync.WaitGroup,
|
||||||
|
c <-chan pkg.Package,
|
||||||
|
opts *ValidateOpts) {
|
||||||
|
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for p := range c {
|
||||||
|
|
||||||
|
if opts.OnlyBuildtime {
|
||||||
|
// Check buildtime compiler/deps
|
||||||
|
err := validatePackage(p, "buildtime", opts, opts.BuildtimeReciper, opts.BuildtimeCacheDeps)
|
||||||
|
if err != nil {
|
||||||
|
opts.AddError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if opts.OnlyRuntime {
|
||||||
|
|
||||||
|
// Check runtime installer/deps
|
||||||
|
err := validatePackage(p, "runtime", opts, opts.RuntimeReciper, opts.RuntimeCacheDeps)
|
||||||
|
if err != nil {
|
||||||
|
opts.AddError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Check runtime installer/deps
|
||||||
|
err := validatePackage(p, "runtime", opts, opts.RuntimeReciper, opts.RuntimeCacheDeps)
|
||||||
|
if err != nil {
|
||||||
|
opts.AddError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check buildtime compiler/deps
|
||||||
|
err = validatePackage(p, "buildtime", opts, opts.BuildtimeReciper, opts.BuildtimeCacheDeps)
|
||||||
|
if err != nil {
|
||||||
|
opts.AddError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initOpts(opts *ValidateOpts, onlyRuntime, onlyBuildtime, withSolver bool, treePaths []string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
opts.OnlyBuildtime = onlyBuildtime
|
||||||
|
opts.OnlyRuntime = onlyRuntime
|
||||||
|
opts.WithSolver = withSolver
|
||||||
|
opts.RuntimeReciper = nil
|
||||||
|
opts.BuildtimeReciper = nil
|
||||||
|
opts.BrokenPkgs = 0
|
||||||
|
opts.BrokenDeps = 0
|
||||||
|
|
||||||
|
if onlyBuildtime {
|
||||||
|
opts.BuildtimeReciper = (tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))).(*tree.CompilerRecipe)
|
||||||
|
} else if onlyRuntime {
|
||||||
|
opts.RuntimeReciper = (tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))).(*tree.InstallerRecipe)
|
||||||
|
} else {
|
||||||
|
opts.BuildtimeReciper = (tree.NewCompilerRecipe(pkg.NewInMemoryDatabase(false))).(*tree.CompilerRecipe)
|
||||||
|
opts.RuntimeReciper = (tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))).(*tree.InstallerRecipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.RuntimeCacheDeps = pkg.NewInMemoryDatabase(false).(*pkg.InMemoryDatabase)
|
||||||
|
opts.BuildtimeCacheDeps = pkg.NewInMemoryDatabase(false).(*pkg.InMemoryDatabase)
|
||||||
|
|
||||||
|
for _, treePath := range treePaths {
|
||||||
|
Info(fmt.Sprintf("Loading :deciduous_tree: %s...", treePath))
|
||||||
|
if opts.BuildtimeReciper != nil {
|
||||||
|
err = opts.BuildtimeReciper.Load(treePath)
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Error on load tree ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if opts.RuntimeReciper != nil {
|
||||||
|
err = opts.RuntimeReciper.Load(treePath)
|
||||||
|
if err != nil {
|
||||||
|
Fatal("Error on load tree ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.RegExcludes, err = helpers.CreateRegexArray(opts.Excludes)
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err.Error())
|
||||||
|
}
|
||||||
|
opts.RegMatches, err = helpers.CreateRegexArray(opts.Matches)
|
||||||
|
if err != nil {
|
||||||
|
Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTreeValidateCommand() *cobra.Command {
|
func NewTreeValidateCommand() *cobra.Command {
|
||||||
var excludes []string
|
var excludes []string
|
||||||
var matches []string
|
var matches []string
|
||||||
var treePaths []string
|
var treePaths []string
|
||||||
|
var opts ValidateOpts
|
||||||
|
|
||||||
var ans = &cobra.Command{
|
var ans = &cobra.Command{
|
||||||
Use: "validate [OPTIONS]",
|
Use: "validate [OPTIONS]",
|
||||||
Short: "Validate a tree or a list of packages",
|
Short: "Validate a tree or a list of packages",
|
||||||
Args: cobra.OnlyValidArgs,
|
Args: cobra.OnlyValidArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
onlyRuntime, _ := cmd.Flags().GetBool("only-runtime")
|
||||||
|
onlyBuildtime, _ := cmd.Flags().GetBool("only-buildtime")
|
||||||
|
|
||||||
if len(treePaths) < 1 {
|
if len(treePaths) < 1 {
|
||||||
Fatal("Mandatory tree param missing.")
|
Fatal("Mandatory tree param missing.")
|
||||||
}
|
}
|
||||||
|
if onlyRuntime && onlyBuildtime {
|
||||||
|
Fatal("Both --only-runtime and --only-buildtime options are not possibile.")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
var reciper tree.Builder
|
||||||
|
|
||||||
concurrency := LuetCfg.GetGeneral().Concurrency
|
concurrency := LuetCfg.GetGeneral().Concurrency
|
||||||
|
|
||||||
withSolver, _ := cmd.Flags().GetBool("with-solver")
|
withSolver, _ := cmd.Flags().GetBool("with-solver")
|
||||||
|
onlyRuntime, _ := cmd.Flags().GetBool("only-runtime")
|
||||||
|
onlyBuildtime, _ := cmd.Flags().GetBool("only-buildtime")
|
||||||
|
|
||||||
reciper := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))
|
opts.Excludes = excludes
|
||||||
for _, treePath := range treePaths {
|
opts.Matches = matches
|
||||||
err := reciper.Load(treePath)
|
initOpts(&opts, onlyRuntime, onlyBuildtime, withSolver, treePaths)
|
||||||
if err != nil {
|
|
||||||
Fatal("Error on load tree ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
regExcludes, err := helpers.CreateRegexArray(excludes)
|
// We need at least one valid reciper for get list of the packages.
|
||||||
if err != nil {
|
if onlyBuildtime {
|
||||||
Fatal(err.Error())
|
reciper = opts.BuildtimeReciper
|
||||||
}
|
} else {
|
||||||
regMatches, err := helpers.CreateRegexArray(matches)
|
reciper = opts.RuntimeReciper
|
||||||
if err != nil {
|
|
||||||
Fatal(err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
all := make(chan pkg.Package)
|
all := make(chan pkg.Package)
|
||||||
errs := make(chan error)
|
|
||||||
|
|
||||||
var wg = new(sync.WaitGroup)
|
var wg = new(sync.WaitGroup)
|
||||||
|
|
||||||
for i := 0; i < concurrency; i++ {
|
for i := 0; i < concurrency; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go validateWorker(i, wg, all,
|
go validateWorker(i, wg, all, &opts)
|
||||||
reciper, withSolver, regExcludes, regMatches, excludes, matches,
|
|
||||||
errs)
|
|
||||||
}
|
}
|
||||||
for _, p := range reciper.GetDatabase().World() {
|
for _, p := range reciper.GetDatabase().World() {
|
||||||
all <- p
|
all <- p
|
||||||
@@ -286,11 +436,10 @@ func NewTreeValidateCommand() *cobra.Command {
|
|||||||
// Wait separately and once done close the channel
|
// Wait separately and once done close the channel
|
||||||
go func() {
|
go func() {
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
close(errs)
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
stringerrs := []string{}
|
stringerrs := []string{}
|
||||||
for e := range errs {
|
for _, e := range opts.Errors {
|
||||||
stringerrs = append(stringerrs, e.Error())
|
stringerrs = append(stringerrs, e.Error())
|
||||||
}
|
}
|
||||||
sort.Strings(stringerrs)
|
sort.Strings(stringerrs)
|
||||||
@@ -300,9 +449,9 @@ func NewTreeValidateCommand() *cobra.Command {
|
|||||||
|
|
||||||
// fmt.Println("Broken packages:", brokenPkgs, "(", brokenDeps, "deps ).")
|
// fmt.Println("Broken packages:", brokenPkgs, "(", brokenDeps, "deps ).")
|
||||||
if len(stringerrs) != 0 {
|
if len(stringerrs) != 0 {
|
||||||
|
Error(fmt.Sprintf("Found %d broken packages and %d broken deps.",
|
||||||
|
opts.BrokenPkgs, opts.BrokenDeps))
|
||||||
Fatal("Errors: " + strconv.Itoa(len(stringerrs)))
|
Fatal("Errors: " + strconv.Itoa(len(stringerrs)))
|
||||||
// if brokenPkgs > 0 {
|
|
||||||
//os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
Info("All good! :white_check_mark:")
|
Info("All good! :white_check_mark:")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@@ -310,6 +459,8 @@ func NewTreeValidateCommand() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ans.Flags().Bool("only-runtime", false, "Check only runtime dependencies.")
|
||||||
|
ans.Flags().Bool("only-buildtime", false, "Check only buildtime dependencies.")
|
||||||
ans.Flags().BoolP("with-solver", "s", false,
|
ans.Flags().BoolP("with-solver", "s", false,
|
||||||
"Enable check of requires also with solver.")
|
"Enable check of requires also with solver.")
|
||||||
ans.Flags().StringSliceVarP(&treePaths, "tree", "t", []string{},
|
ans.Flags().StringSliceVarP(&treePaths, "tree", "t", []string{},
|
||||||
|
@@ -16,6 +16,12 @@
|
|||||||
# Enable JSON log format instead of console mode.
|
# Enable JSON log format instead of console mode.
|
||||||
# json_format: false.
|
# json_format: false.
|
||||||
#
|
#
|
||||||
|
# Disable/Enable color
|
||||||
|
# color: true
|
||||||
|
#
|
||||||
|
# Enable/Disable emoji
|
||||||
|
# enable_emoji: true
|
||||||
|
#
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
# General configuration section:
|
# General configuration section:
|
||||||
# ---------------------------------------------
|
# ---------------------------------------------
|
||||||
|
@@ -27,7 +27,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
system "github.com/Luet-lab/moby/pkg/system"
|
system "github.com/docker/docker/pkg/system"
|
||||||
gzip "github.com/klauspost/pgzip"
|
gzip "github.com/klauspost/pgzip"
|
||||||
|
|
||||||
//"strconv"
|
//"strconv"
|
||||||
|
@@ -23,15 +23,20 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Docker backend", func() {
|
var _ = Describe("Docker image diffs", func() {
|
||||||
var b compiler.CompilerBackend
|
var b compiler.CompilerBackend
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
b = NewSimpleDockerBackend()
|
b = NewSimpleDockerBackend()
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("Simple Docker backend satisfies main interface functionalities", func() {
|
Context("Generate diffs from docker images", func() {
|
||||||
It("Builds and generate tars", func() {
|
It("Detect no changes", func() {
|
||||||
|
err := b.DownloadImage(compiler.CompilerBackendOptions{
|
||||||
|
ImageName: "alpine:latest",
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
layers, err := GenerateChanges(b, "alpine:latest", "alpine:latest")
|
layers, err := GenerateChanges(b, "alpine:latest", "alpine:latest")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(len(layers)).To(Equal(1))
|
Expect(len(layers)).To(Equal(1))
|
||||||
@@ -40,7 +45,16 @@ var _ = Describe("Docker backend", func() {
|
|||||||
Expect(len(layers[0].Diffs.Deletions)).To(Equal(0))
|
Expect(len(layers[0].Diffs.Deletions)).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("Builds and generate tars", func() {
|
It("Detects additions and changed files", func() {
|
||||||
|
err := b.DownloadImage(compiler.CompilerBackendOptions{
|
||||||
|
ImageName: "quay.io/mocaccino/micro",
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
err = b.DownloadImage(compiler.CompilerBackendOptions{
|
||||||
|
ImageName: "quay.io/mocaccino/extra",
|
||||||
|
})
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
layers, err := GenerateChanges(b, "quay.io/mocaccino/micro", "quay.io/mocaccino/extra")
|
layers, err := GenerateChanges(b, "quay.io/mocaccino/micro", "quay.io/mocaccino/extra")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(len(layers)).To(Equal(1))
|
Expect(len(layers)).To(Equal(1))
|
||||||
|
@@ -553,7 +553,8 @@ func (cs *LuetCompiler) compile(concurrency int, keepPermissions bool, p Compila
|
|||||||
|
|
||||||
if len(p.GetPackage().GetRequires()) == 0 && p.GetImage() == "" {
|
if len(p.GetPackage().GetRequires()) == 0 && p.GetImage() == "" {
|
||||||
Error("Package with no deps and no seed image supplied, bailing out")
|
Error("Package with no deps and no seed image supplied, bailing out")
|
||||||
return nil, errors.New("Package " + p.GetPackage().GetFingerPrint() + "with no deps and no seed image supplied, bailing out")
|
return nil, errors.New("Package " + p.GetPackage().GetFingerPrint() +
|
||||||
|
" with no deps and no seed image supplied, bailing out")
|
||||||
}
|
}
|
||||||
|
|
||||||
targetAssertion := p.GetSourceAssertion().Search(p.GetPackage().GetFingerPrint())
|
targetAssertion := p.GetSourceAssertion().Search(p.GetPackage().GetFingerPrint())
|
||||||
|
@@ -64,6 +64,7 @@ type Package interface {
|
|||||||
GetCategory() string
|
GetCategory() string
|
||||||
|
|
||||||
GetVersion() string
|
GetVersion() string
|
||||||
|
SetVersion(string)
|
||||||
RequiresContains(PackageDatabase, Package) (bool, error)
|
RequiresContains(PackageDatabase, Package) (bool, error)
|
||||||
Matches(m Package) bool
|
Matches(m Package) bool
|
||||||
BumpBuildVersion() error
|
BumpBuildVersion() error
|
||||||
@@ -327,6 +328,9 @@ func (p *DefaultPackage) GetName() string {
|
|||||||
func (p *DefaultPackage) GetVersion() string {
|
func (p *DefaultPackage) GetVersion() string {
|
||||||
return p.Version
|
return p.Version
|
||||||
}
|
}
|
||||||
|
func (p *DefaultPackage) SetVersion(v string) {
|
||||||
|
p.Version = v
|
||||||
|
}
|
||||||
func (p *DefaultPackage) GetDescription() string {
|
func (p *DefaultPackage) GetDescription() string {
|
||||||
return p.Description
|
return p.Description
|
||||||
}
|
}
|
||||||
|
@@ -60,19 +60,15 @@ testInstall() {
|
|||||||
docker build --rm --no-cache -t luet:test .
|
docker build --rm --no-cache -t luet:test .
|
||||||
docker rm luet-runtime-test || true
|
docker rm luet-runtime-test || true
|
||||||
docker run --name luet-runtime-test \
|
docker run --name luet-runtime-test \
|
||||||
-ti -v /tmp:/tmp \
|
-v /tmp:/tmp \
|
||||||
-v $tmpdir/luet.yaml:/etc/luet/luet.yaml:ro \
|
-v $tmpdir/luet.yaml:/etc/luet/luet.yaml:ro \
|
||||||
luet:test install seed/alpine
|
luet:test install seed/alpine
|
||||||
installst=$?
|
installst=$?
|
||||||
assertEquals 'install test successfully' "0" "$installst"
|
assertEquals 'install test successfully' "0" "$installst"
|
||||||
|
|
||||||
docker commit luet-runtime-test luet-runtime-test-image
|
docker commit luet-runtime-test luet-runtime-test-image
|
||||||
test=$(docker run --rm -t --entrypoint /bin/sh luet-runtime-test-image -c 'echo "ftw"')
|
test=$(docker run --rm --entrypoint /bin/sh luet-runtime-test-image -c 'echo "ftw"')
|
||||||
assertContains 'generated image runs successfully' "$test" "ftw"
|
assertContains 'generated image runs successfully' "$test" "ftw"
|
||||||
# docker rm luet-runtime-test || true
|
|
||||||
# docker rmi luet-runtime-test-image || true
|
|
||||||
|
|
||||||
# docker rmi luet:test || true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load shUnit2.
|
# Load shUnit2.
|
||||||
|
Reference in New Issue
Block a user