Skip to content

Commit

Permalink
Add composer files resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
4ernovm committed Nov 22, 2023
1 parent f8a0330 commit 9a2fd0f
Show file tree
Hide file tree
Showing 17 changed files with 422 additions and 6 deletions.
22 changes: 22 additions & 0 deletions build/docker/alpine.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,27 @@ RUN apk --no-cache --update add \

RUN dotnet --version

RUN echo 'https://dl-cdn.alpinelinux.org/alpine/v3.14/community' >> /etc/apk/repositories
RUN echo 'https://dl-cdn.alpinelinux.org/alpine/v3.14/main' >> /etc/apk/repositories
RUN apk --update --no-cache add \
php \
php-json \
php-openssl \
php-curl \
php-dom \
php-mbstring \
php-xml \
php-phar \
php-tokenizer \
php-xmlwriter \
php-session \
php-ctype

RUN php -v

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer

RUN php -v && composer --version

# Put copy at the end to speedup Docker build by caching previous RUNs and run those concurrently
COPY --from=dev /cli/debricked /usr/bin/debricked
21 changes: 21 additions & 0 deletions build/docker/debian.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,26 @@ RUN apt -y update && apt -y upgrade && apt -y install openjdk-11-jre \

RUN dotnet --version

RUN apt -y update && apt -y upgrade && apt -y install \
php \
php-json \
php-openssl \
php-curl \
php-dom \
php-mbstring \
php-xml \
php-phar \
php-tokenizer \
php-xmlwriter \
php-simplexml \
php-xmlreader \
php-session \
php-ctype && \
apt -y clean && rm -rf /var/lib/apt/lists/*

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer

RUN php -v && composer --version

# Put copy at the end to speedup Docker build by caching previous RUNs and run those concurrently
COPY --from=dev /cli/debricked /usr/bin/debricked
45 changes: 45 additions & 0 deletions internal/resolution/pm/composer/cmd_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package composer

import (
"os/exec"
"path/filepath"
)

type ICmdFactory interface {
MakeInstallCmd(command string, file string) (*exec.Cmd, error)
}

type IExecPath interface {
LookPath(file string) (string, error)
}

type ExecPath struct {
}

func (ExecPath) LookPath(file string) (string, error) {
return exec.LookPath(file)
}

type CmdFactory struct {
execPath IExecPath
}

func (cmdf CmdFactory) MakeInstallCmd(command string, file string) (*exec.Cmd, error) {
path, err := cmdf.execPath.LookPath(command)

fileDir := filepath.Dir(file)

return &exec.Cmd{
Path: path,
Args: []string{command, "update",
"--no-interaction", // We can't answer any prompts...
"--no-scripts", // Avoid risky scripts
"--ignore-platform-reqs", // We won't run the code, so we don't care about the platform
"--no-autoloader", // We won't execute any code, no need for autoloader
"--no-install", // No need to install packages
"--no-plugins", // We won't run the code, so no plugins needed
"--no-audit", // We don't want to run an audit
},
Dir: fileDir,
}, err
}
19 changes: 19 additions & 0 deletions internal/resolution/pm/composer/cmd_factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package composer

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestMakeInstallCmd(t *testing.T) {
composerCommand := "composer"
cmd, err := CmdFactory{
execPath: ExecPath{},
}.MakeInstallCmd(composerCommand, "file")
assert.NoError(t, err)
assert.NotNil(t, cmd)
args := cmd.Args
assert.Contains(t, args, "composer")
assert.Contains(t, args, "update")
}
62 changes: 62 additions & 0 deletions internal/resolution/pm/composer/job.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package composer

import (
"github.com/debricked/cli/internal/resolution/job"
)

const (
composer = "composer"
)

type Job struct {
job.BaseJob
install bool
composerCommand string
cmdFactory ICmdFactory
}

func NewJob(
file string,
install bool,
cmdFactory ICmdFactory,
) *Job {
return &Job{
BaseJob: job.NewBaseJob(file),
install: install,
cmdFactory: cmdFactory,
}
}

func (j *Job) Install() bool {
return j.install
}

func (j *Job) Run() {
if j.install {

j.SendStatus("installing dependencies")
_, err := j.runInstallCmd()
if err != nil {
j.Errors().Critical(err)

return
}
}

}

func (j *Job) runInstallCmd() ([]byte, error) {

j.composerCommand = composer
installCmd, err := j.cmdFactory.MakeInstallCmd(j.composerCommand, j.GetFile())
if err != nil {
return nil, err
}

installCmdOutput, err := installCmd.Output()
if err != nil {
return nil, j.GetExitError(err)
}

return installCmdOutput, nil
}
64 changes: 64 additions & 0 deletions internal/resolution/pm/composer/job_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package composer

import (
"errors"
"testing"

jobTestdata "github.com/debricked/cli/internal/resolution/job/testdata"
"github.com/debricked/cli/internal/resolution/pm/composer/testdata"
"github.com/stretchr/testify/assert"
)

const (
badName = "bad-name"
)

func TestNewJob(t *testing.T) {
j := NewJob("file", false, CmdFactory{
execPath: ExecPath{},
})
assert.Equal(t, "file", j.GetFile())
assert.False(t, j.Errors().HasError())
}

func TestRunInstall(t *testing.T) {
cmdFactoryMock := testdata.NewEchoCmdFactory()
j := NewJob("file", false, cmdFactoryMock)

_, err := j.runInstallCmd()
assert.NoError(t, err)

assert.False(t, j.Errors().HasError())
}

func TestInstall(t *testing.T) {
j := Job{install: true}
assert.Equal(t, true, j.Install())

j = Job{install: false}
assert.Equal(t, false, j.Install())
}

func TestRunInstallCmdErr(t *testing.T) {
cmdErr := errors.New("cmd-error")
cmdFactoryMock := testdata.NewEchoCmdFactory()
cmdFactoryMock.MakeInstallErr = cmdErr
j := NewJob("file", true, cmdFactoryMock)

go jobTestdata.WaitStatus(j)
j.Run()

assert.Len(t, j.Errors().GetAll(), 1)
assert.Contains(t, j.Errors().GetAll(), cmdErr)
}

func TestRunInstallCmdOutputErr(t *testing.T) {
cmdMock := testdata.NewEchoCmdFactory()
cmdMock.InstallCmdName = badName
j := NewJob("file", true, cmdMock)

go jobTestdata.WaitStatus(j)
j.Run()

jobTestdata.AssertPathErr(t, j.Errors())
}
23 changes: 23 additions & 0 deletions internal/resolution/pm/composer/pm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package composer

const Name = "composer"

type Pm struct {
name string
}

func NewPm() Pm {
return Pm{
name: Name,
}
}

func (pm Pm) Name() string {
return pm.name
}

func (Pm) Manifests() []string {
return []string{
`composer\.json$`,
}
}
40 changes: 40 additions & 0 deletions internal/resolution/pm/composer/pm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package composer

import (
"regexp"
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewPm(t *testing.T) {
pm := NewPm()
assert.Equal(t, Name, pm.name)
}

func TestName(t *testing.T) {
pm := NewPm()
assert.Equal(t, Name, pm.Name())
}

func TestManifests(t *testing.T) {
pm := Pm{}
manifests := pm.Manifests()
assert.Len(t, manifests, 1)
manifest := manifests[0]
assert.Equal(t, `composer\.json$`, manifest)
_, err := regexp.Compile(manifest)
assert.NoError(t, err)

cases := map[string]bool{
"composer.json": true,
"composer.lock": false,
"package-lock.json": false,
}
for file, isMatch := range cases {
t.Run(file, func(t *testing.T) {
matched, _ := regexp.MatchString(manifest, file)
assert.Equal(t, isMatch, matched)
})
}
}
29 changes: 29 additions & 0 deletions internal/resolution/pm/composer/strategy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package composer

import (
"github.com/debricked/cli/internal/resolution/job"
)

type Strategy struct {
files []string
}

func (s Strategy) Invoke() ([]job.IJob, error) {
var jobs []job.IJob
for _, file := range s.files {
jobs = append(jobs, NewJob(
file,
true,
CmdFactory{
execPath: ExecPath{},
},
),
)
}

return jobs, nil
}

func NewStrategy(files []string) Strategy {
return Strategy{files}
}
43 changes: 43 additions & 0 deletions internal/resolution/pm/composer/strategy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package composer

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestNewStrategy(t *testing.T) {
s := NewStrategy(nil)
assert.NotNil(t, s)
assert.Len(t, s.files, 0)

s = NewStrategy([]string{})
assert.NotNil(t, s)
assert.Len(t, s.files, 0)

s = NewStrategy([]string{"file"})
assert.NotNil(t, s)
assert.Len(t, s.files, 1)

s = NewStrategy([]string{"file-1", "file-2"})
assert.NotNil(t, s)
assert.Len(t, s.files, 2)
}

func TestInvokeNoFiles(t *testing.T) {
s := NewStrategy([]string{})
jobs, _ := s.Invoke()
assert.Empty(t, jobs)
}

func TestInvokeOneFile(t *testing.T) {
s := NewStrategy([]string{"file"})
jobs, _ := s.Invoke()
assert.Len(t, jobs, 1)
}

func TestInvokeManyFiles(t *testing.T) {
s := NewStrategy([]string{"file-1", "file-2"})
jobs, _ := s.Invoke()
assert.Len(t, jobs, 2)
}
Loading

0 comments on commit 9a2fd0f

Please sign in to comment.