Skip to content

Commit

Permalink
python tests
Browse files Browse the repository at this point in the history
  • Loading branch information
jaredLunde committed May 15, 2024
1 parent 82826db commit bb7fcd3
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 9 deletions.
8 changes: 0 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,11 @@ Detected in order of precedence:
[Java](https://www.java.com/) is a class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible.

#### Detected Files
- `build.gradle`
- `gradlew`
- `pom.{xml,atom,clj,groovy,rb,scala,yml,yaml}`

#### Version Detection
JDK version:
- `.tool-versions` - `java {VERSION}`
Gradle version:
- `.tool-versions` - `gradle {VERSION}`
Maven version:
- `.tool-versions` - `maven {VERSION}`

Expand All @@ -269,7 +265,6 @@ Maven version:

#### Build Args
- `VERSION` - The version of the JDK to install (default: `17`)
- `GRADLE_VERSION` - The version of Gradle to install (default: `8`)
- `MAVEN_VERSION` - The version of Maven to install (default: `3`)
- `JAVA_OPTS` - The Java options to pass to the JVM (default: `-Xmx512m -Xms256m`)
- `BUILD_CMD` - The command to build the project (default: best guess via source code)
Expand All @@ -280,13 +275,10 @@ Maven version:

#### Build Command
- If Maven: `mvn -DoutputFile=target/mvn-dependency-list.log -B -DskipTests clean dependency:list install`
- If Gradle: `./gradlew clean build -x check -x test`

#### Start Command
- Default: `java $JAVA_OPTS -jar target/*jar`
- If Gradle: `java $JAVA_OPTS -jar $(ls -1 build/libs/*jar | grep -v plain)`
- If Spring Boot: `java -Dserver.port=${PORT} $JAVA_OPTS -jar target/*jar`
- If Spring Boot w/ Gradle: `java -Dserver.port=${PORT} $JAVA_OPTS -jar $(ls -1 build/libs/*jar | grep -v plain)`

---

Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// A library for auto-generating Dockerfiles from project source code.
package dockerfile

import (
Expand All @@ -9,7 +10,7 @@ import (
"github.com/flexstack/new-dockerfile/runtime"
)

// Creates a new Dockerfile generator.
// Creates a new Dockerfile generator. If no logger is provided, a default logger is created.
func New(log ...*slog.Logger) *Dockerfile {
var logger *slog.Logger

Expand Down Expand Up @@ -50,6 +51,7 @@ func (a *Dockerfile) Write(path string) error {
return nil
}

// Lists all runtimes that the Dockerfile generator can auto-generate.
func (a *Dockerfile) ListRuntimes() []runtime.Runtime {
return []runtime.Runtime{
&runtime.Golang{Log: a.log},
Expand All @@ -67,6 +69,7 @@ func (a *Dockerfile) ListRuntimes() []runtime.Runtime {
}
}

// Matches the runtime of the project at the given path.
func (a *Dockerfile) MatchRuntime(path string) (runtime.Runtime, error) {
for _, r := range a.ListRuntimes() {
if r.Match(path) {
Expand Down
4 changes: 4 additions & 0 deletions runtime/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package runtime

// An interface that all runtimes must implement.
type Runtime interface {
// Returns the name of the runtime.
Name() RuntimeName
// Returns true if the runtime can be used for the given path.
Match(path string) bool
// Generates a Dockerfile for the given path.
GenerateDockerfile(path string) ([]byte, error)
}

Expand Down
4 changes: 4 additions & 0 deletions runtime/python.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ func (d *Python) GenerateDockerfile(path string) ([]byte, error) {
if name, ok := project["name"].(string); ok {
projectName = name
}
} else if project, ok := pyprojectTOML["tool.poetry"].(map[string]interface{}); ok {
if name, ok := project["name"].(string); ok {
projectName = name
}
}
}

Expand Down
154 changes: 154 additions & 0 deletions runtime/python_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package runtime_test

import (
"regexp"
"strings"
"testing"

"github.com/flexstack/new-dockerfile/runtime"
)

func TestPythonMatch(t *testing.T) {
tests := []struct {
name string
path string
expected bool
}{
{
name: "Python project",
path: "../testdata/python",
expected: true,
},
{
name: "Python project with django",
path: "../testdata/python-django",
expected: true,
},
{
name: "Python project with pdm",
path: "../testdata/python-pdm",
expected: true,
},
{
name: "Python project with poetry",
path: "../testdata/python-poetry",
expected: true,
},
{
name: "Python project with pyproject",
path: "../testdata/python-pyproject",
expected: true,
},
{
name: "Not a Python project",
path: "../testdata/deno",
expected: false,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
python := &runtime.Python{Log: logger}
if python.Match(test.path) != test.expected {
t.Errorf("expected %v, got %v", test.expected, python.Match(test.path))
}
})
}
}

func TestPythonGenerateDockerfile(t *testing.T) {
tests := []struct {
name string
path string
expected []any
}{
{
name: "Python project",
path: "../testdata/python",
expected: []any{
`ARG VERSION=3.12`,
`ARG INSTALL_CMD="pip install -r requirements.txt"`,
`ARG START_CMD="python main.py"`,
},
},
{
name: "Python project with django",
path: "../testdata/python-django",
expected: []any{
`ARG VERSION=3.6.0`,
`ARG INSTALL_CMD="PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy"`,
`ARG START_CMD="python manage.py runserver 0.0.0.0:${PORT}"`,
},
},
{
name: "Python project with pdm",
path: "../testdata/python-pdm",
expected: []any{
`ARG VERSION=3.4.1`,
`ARG INSTALL_CMD="pdm install --prod"`,
`ARG START_CMD="python app.py"`,
},
},
{
name: "Python project with poetry",
path: "../testdata/python-poetry",
expected: []any{
`ARG VERSION=3.8.5`,
`ARG INSTALL_CMD="poetry install --no-dev --no-interactive --no-ansi"`,
`ARG START_CMD="python app/main.py"`,
},
},
{
name: "Python project with pyproject",
path: "../testdata/python-pyproject",
expected: []any{
`ARG VERSION=3.12`,
`ARG INSTALL_CMD="pip install --upgrade build setuptools \u0026\u0026 pip install .`,
`ARG START_CMD="python -m pyproject"`,
},
},
{
name: "Not a Python project",
path: "../testdata/deno",
expected: []any{
`ARG VERSION=3.12`,
regexp.MustCompile(`^ARG INSTALL_CMD=$`),
regexp.MustCompile(`^ARG START_CMD=$`),
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
python := &runtime.Python{Log: logger}
dockerfile, err := python.GenerateDockerfile(test.path)
if err != nil {
t.Errorf("unexpected error: %v", err)
}

for _, line := range test.expected {
found := false
lines := strings.Split(string(dockerfile), "\n")

for _, l := range lines {
switch v := line.(type) {
case string:
if strings.Contains(l, v) {
found = true
break
}
case *regexp.Regexp:
if v.MatchString(l) {
found = true
break
}
}
}

if !found {
t.Errorf("expected %v, not found in %v", line, string(dockerfile))
}
}
})
}
}
1 change: 1 addition & 0 deletions testdata/python-django/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python 3.6.0
10 changes: 10 additions & 0 deletions testdata/python-django/Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"
django = "*"

[dev-packages]
59 changes: 59 additions & 0 deletions testdata/python-django/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
1 change: 1 addition & 0 deletions testdata/python-pdm/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.4.1
Empty file added testdata/python-pdm/app.py
Empty file.
Empty file added testdata/python-pdm/pdm.lock
Empty file.
Empty file.
Empty file.
1 change: 1 addition & 0 deletions testdata/python-poetry/runtime.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python-3.8.5
2 changes: 2 additions & 0 deletions testdata/python-pyproject/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[project]
name = "pyproject"
Empty file added testdata/python/main.py
Empty file.
Empty file.

0 comments on commit bb7fcd3

Please sign in to comment.