Skip to content

Commit

Permalink
changes to support gradle wrapper and defaults (#218)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsubramanianaks authored Jul 7, 2023
1 parent b143ed2 commit d419927
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 1 deletion.
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"
}

// 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"

0 comments on commit d419927

Please sign in to comment.