Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes to support gradle wrapper and defaults #218

Merged
merged 7 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func (cc *createCmd) detectLanguage() (*config.DraftConfig, string, error) {

selection := &promptui.Select{
Label: "Linguist detected Java, are you using maven or gradle?",
Items: []string{"gradle", "maven"},
Items: []string{"gradle", "maven", "gradlew"},
}

_, selectResponse, err := selection.Run()
Expand All @@ -209,6 +209,8 @@ func (cc *createCmd) detectLanguage() (*config.DraftConfig, string, error) {

if selectResponse == "gradle" {
lang.Language = "Gradle"
} else if selectResponse == "gradlew" {
lang.Language = "Gradlew"
}
}
}
Expand Down
115 changes: 115 additions & 0 deletions pkg/languages/defaults/gradle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package defaults

import (
"fmt"
"strings"

"github.com/Azure/draft/pkg/reporeader"
log "github.com/sirupsen/logrus"
)

const SOURCE_COMPATIBILITY = "sourceCompatibility"
const TARGET_COMPATIBILITY = "targetCompatibility"
const SERVER_PORT = "server.port"
const GRADLE_FILE_FORMAT = "*.gradle"

type GradleExtractor struct {
}

// GetName implements reporeader.VariableExtractor
func (*GradleExtractor) GetName() string {
return "gradle"
}

// MatchesLanguage implements reporeader.VariableExtractor
func (*GradleExtractor) MatchesLanguage(lowerlang string) bool {
return lowerlang == "gradle" || lowerlang == "gradlew"
bfoley13 marked this conversation as resolved.
Show resolved Hide resolved
}

// ReadDefaults implements reporeader.VariableExtractor
func (*GradleExtractor) ReadDefaults(r reporeader.RepoReader) (map[string]string, error) {
separatorsSet := createSeparatorsSet()
cutSet := createCutSet()
extractedValues := make(map[string]string)
files, err := r.FindFiles(".", []string{GRADLE_FILE_FORMAT}, 2)
if err != nil {
return nil, fmt.Errorf("error finding gradle files: %v", err)
}
if len(files) > 0 {
f, err := r.ReadFile(files[0])
if err != nil {
log.Warn("Unable to read gradle file, skipping detection")
return nil, nil
}
content := string(f)
// this separator is used to split the line from build.gradle ex: sourceCompatibility = '1.8'
// output will be ['sourceCompatibility', '1.8'] or ["sourceCompatibility", "1.8"]
separatorFunc := func(c rune) bool {
return separatorsSet.Contains(c)
}
// this func takes care of removing the single or double quotes from split array output
cutset := func(c rune) bool { return cutSet.Contains(c) }
if strings.Contains(content, SOURCE_COMPATIBILITY) || strings.Contains(content, TARGET_COMPATIBILITY) || strings.Contains(content, SERVER_PORT) {
stringAfterSplit := strings.FieldsFunc(content, separatorFunc)
for i, s := range stringAfterSplit {
if i+1 >= len(stringAfterSplit) {
break
}
if s == SOURCE_COMPATIBILITY {
detectedVersion := strings.TrimFunc(stringAfterSplit[i+1], cutset)
detectedVersion = detectedVersion + "-jre"
extractedValues["VERSION"] = detectedVersion
} else if s == TARGET_COMPATIBILITY {
detectedBuilderVersion := strings.TrimFunc(stringAfterSplit[i+1], cutset)
detectedBuilderVersion = "jdk" + detectedBuilderVersion
extractedValues["BUILDERVERSION"] = detectedBuilderVersion
} else if s == SERVER_PORT {
detectedPort := strings.TrimFunc(stringAfterSplit[i+1], cutset)
extractedValues["PORT"] = detectedPort
}
}
}
}

return extractedValues, nil
}

func createSeparatorsSet() Set {
separatorsSet := NewSet()
separatorsSet.Add(' ')
separatorsSet.Add('=')
separatorsSet.Add('\n')
separatorsSet.Add('\r')
separatorsSet.Add('\t')
separatorsSet.Add('{')
separatorsSet.Add('}')
separatorsSet.Add('[')
separatorsSet.Add(']')
separatorsSet.Add('-')
separatorsSet.Add(':')
return separatorsSet
}

func createCutSet() Set {
cutSet := NewSet()
cutSet.Add('\'')
cutSet.Add('"')
return cutSet
}

type Set map[interface{}]struct{}

func NewSet() Set {
return make(Set)
}

func (s Set) Add(item interface{}) {
s[item] = struct{}{}
}

func (s Set) Contains(item interface{}) bool {
_, ok := s[item]
return ok
}

var _ reporeader.VariableExtractor = &GradleExtractor{}
116 changes: 116 additions & 0 deletions pkg/languages/defaults/gradle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package defaults

import (
"io/ioutil"
"reflect"
"testing"

"github.com/Azure/draft/pkg/reporeader"
)

func TestGradleExtractor_ReadDefaults(t *testing.T) {
content, err := ioutil.ReadFile("testdata/sample.gradle")
if err != nil {
t.Errorf("error reading sample_build.gradle: %v", err)
}
type args struct {
r reporeader.RepoReader
}
tests := []struct {
name string
args args
want map[string]string
wantErr bool
}{
{
name: "extract gradle jre version with spaces",
args: args{
r: reporeader.TestRepoReader{
Files: map[string][]byte{
"build.gradle": []byte("group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility=\"11\" targetCompatibility='11'"),
},
},
},
want: map[string]string{
"VERSION": "11-jre",
"BUILDERVERSION": "jdk11",
},
wantErr: false,
},
{
name: "extract gradle jre version with new lines",
args: args{
r: reporeader.TestRepoReader{
Files: map[string][]byte{
"build.gradle": []byte("group = 'com.example'\nversion = '0.0.1-SNAPSHOT'\nsourceCompatibility=\"11\"\ntargetCompatibility='11'"),
},
},
},
want: map[string]string{
"VERSION": "11-jre",
"BUILDERVERSION": "jdk11",
},
wantErr: false,
},
{
name: "extract gradle jre version with tabs",
args: args{
r: reporeader.TestRepoReader{
Files: map[string][]byte{
"build.gradle": []byte("group = 'com.example'\tversion = '0.0.1-SNAPSHOT'\tsourceCompatibility= \"12\" \ntargetCompatibility='11'"),
},
},
},
want: map[string]string{
"VERSION": "12-jre",
"BUILDERVERSION": "jdk11",
},
wantErr: false,
},
{
name: "extract gradle jre version with double spaces",
args: args{
r: reporeader.TestRepoReader{
Files: map[string][]byte{
"build.gradle": []byte("group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility=\"12\"\ntargetCompatibility='11'"),
},
},
},
want: map[string]string{
"VERSION": "12-jre",
"BUILDERVERSION": "jdk11",
},
wantErr: false,
},
{
name: "extract gradle jre version reading from a file",
args: args{
r: reporeader.TestRepoReader{
Files: map[string][]byte{
"build.gradle": content,
},
},
},
want: map[string]string{
"VERSION": "11-jre",
"BUILDERVERSION": "jdk11",
"PORT": "8081",
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := GradleExtractor{}
got, err := p.ReadDefaults(tt.args.r)
if (err != nil) != tt.wantErr {
t.Errorf("ReadDefaults() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ReadDefaults() got = %v, want %v", got, tt.want)
}
})
}

}
39 changes: 39 additions & 0 deletions pkg/languages/defaults/testdata/sample.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
plugins {
id 'org.springframework.boot' version '2.6.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = "11"
targetCompatibility = '11'

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
}

bootRun {
args = ['--server.port=8081']
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml'
implementation 'com.networknt:json-schema-validator:1.0.66'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
useJUnitPlatform()
}
1 change: 1 addition & 0 deletions pkg/languages/languages.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func CreateLanguagesFromEmbedFS(dockerfileTemplates embed.FS, dest string) *Lang
func (l *Languages) ExtractDefaults(lowerLang string, r reporeader.RepoReader) ([]config.BuilderVarDefault, error) {
extractors := []reporeader.VariableExtractor{
&defaults.PythonExtractor{},
&defaults.GradleExtractor{},
}
extractedValues := make(map[string]string)
var extractedDefaults []config.BuilderVarDefault
Expand Down
2 changes: 2 additions & 0 deletions template/dockerfiles/gradlew/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dockerfile
charts/
17 changes: 17 additions & 0 deletions template/dockerfiles/gradlew/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM gradle:{{BUILDERVERSION}} as BUILD

COPY --chown=gradle:gradle . /project
COPY gradlew gradlew
COPY gradle/wrapper gradle/wrapper
RUN chmod +x gradle/wrapper
RUN chmod +x gradlew
RUN ./gradlew -i -s -b /project/build.gradle clean build

FROM eclipse-temurin:{{VERSION}}
ENV PORT {{PORT}}
EXPOSE {{PORT}}

COPY --from=BUILD /project/build/libs/* /opt/
WORKDIR /opt/
RUN ls -l
CMD ["/bin/bash", "-c", "find -type f -name '*SNAPSHOT.jar' | xargs java -jar"]
22 changes: 22 additions & 0 deletions template/dockerfiles/gradlew/draft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
language: gradle
displayName: Gradle
nameOverrides:
- path: "dockerignore"
prefix: "."
variables:
- name: "PORT"
description: "the port exposed in the application"
type: int
- name: "BUILDERVERSION"
description: "the version of gradle used during the builder stage to generate the executable"
exampleValues: ["jdk8","jdk11","jdk17","jdk19"]
- name: "VERSION"
description: "the version of openjdk used by the application"
exampleValues: ["8-jre","11-jre","17-jre","19-jre"]
variableDefaults:
- name: "BUILDERVERSION"
value: "jdk11"
- name: "VERSION"
value: "11-jre"
- name: "PORT"
value: "80"
Loading