@elastic.io/component-build-helper
Advanced tools
Comparing version 0.0.5-dev.12 to 0.0.5-dev.13
@@ -27,2 +27,4 @@ "use strict"; | ||
'build.gradle', | ||
'gradlew', | ||
// Common | ||
'component.json', | ||
@@ -29,0 +31,0 @@ 'Dockerfile', |
@@ -23,8 +23,12 @@ import { ComponentContextLoader } from './ComponentContextLoader'; | ||
protected getLabels(): string[]; | ||
protected prepareLabel(str: string, chunkSize?: number): string; | ||
protected checkIsDockerfilePredefined(): void; | ||
} | ||
export declare class GradleDockerfileGenerator extends DockerfileGenerator { | ||
readonly defaultGradleVersion = "7.4.2"; | ||
private javaVersion; | ||
private sailorBuildGralde; | ||
constructor(componentContextLoader: ComponentContextLoader); | ||
static detect(componentContextLoader: ComponentContextLoader): Promise<boolean>; | ||
private isWrapperExists; | ||
genDockerfile(): string; | ||
@@ -34,3 +38,3 @@ getComponentBuildImage(): Promise<string> | string; | ||
/** | ||
* Load needed information from package.json and calculate needed nodejs version | ||
* Load needed information from build.gradle and calculate needed java version | ||
*/ | ||
@@ -37,0 +41,0 @@ init(): Promise<void>; |
@@ -13,2 +13,4 @@ "use strict"; | ||
const parser_1 = __importDefault(require("gradle-to-js/lib/parser")); | ||
const fs_1 = require("fs"); | ||
const path_1 = __importDefault(require("path")); | ||
class DockerfileGenerator { | ||
@@ -58,6 +60,16 @@ constructor(componentContextLoader) { | ||
// need to stringify 2 times to get escaped json string | ||
`LABEL elastic.io.component=${JSON.stringify(JSON.stringify(this.componentJson))}`, | ||
`LABEL elastic.io.logo=${this._icon}` | ||
`LABEL elastic.io.component=${this.prepareLabel(JSON.stringify(JSON.stringify(this.componentJson)))}`, | ||
`LABEL elastic.io.logo="${this.prepareLabel(this._icon)}"` | ||
]; | ||
} | ||
// dockerfile line can not be greater than max allowed size of 65535 | ||
// So just split long labels to lines with such size | ||
prepareLabel(str, chunkSize = 65500) { | ||
const chunks = []; | ||
for (let i = 0; i < str.length; i += chunkSize) { | ||
const chunk = str.slice(i, i + chunkSize); | ||
chunks.push(chunk); | ||
} | ||
return chunks.join('\\\n'); | ||
} | ||
// Developer can specify custom dockerfile for component. | ||
@@ -77,2 +89,3 @@ // We need to add labels in such cases | ||
super(componentContextLoader); | ||
this.defaultGradleVersion = '7.4.2'; | ||
this._componentLanguage = index_1.COMPONENT_LANGUAGE.JAVA; | ||
@@ -84,20 +97,54 @@ } | ||
} | ||
// TODO use apprunner for now. implement new dockerfile structure for gradle components | ||
isWrapperExists() { | ||
return this.componentContextLoader.context['gradlew']; | ||
} | ||
genDockerfile() { | ||
return this.predefinedDockerfile || [ | ||
'FROM elasticio/apprunner:production', | ||
'ADD ./ /home/apprunner', | ||
...this.getLabels() | ||
this.checkInit(); | ||
if (this.predefinedDockerfile) { | ||
return this.predefinedDockerfile; | ||
} | ||
const gradle = []; | ||
const build = []; | ||
if (!this.isWrapperExists()) { | ||
// installing gradle, because wrapper is not exists in the component | ||
gradle.push(`FROM amazoncorretto:${this.getComponentBuildImage()} as gradle`, `ARG GRADLE_VERSION=${this.defaultGradleVersion}`, 'ENV GRADLE_ARCHIVE gradle-$GRADLE_VERSION-bin.zip', 'WORKDIR /opt', 'RUN apk update && apk add --no-cache wget libstdc++ && rm -rf /var/cache/apk/*', 'RUN wget --no-verbose https://services.gradle.org/distributions/$GRADLE_ARCHIVE', 'RUN unzip -q $GRADLE_ARCHIVE && rm $GRADLE_ARCHIVE', 'ENV PATH "$PATH:/opt/gradle-$GRADLE_VERSION/bin/"'); | ||
build.push('FROM gradle as build'); | ||
} | ||
else { | ||
build.push(`FROM amazoncorretto:${this.getComponentBuildImage()} as build`); | ||
} | ||
build.push('ARG CLASSES_MAIN_DIR=./build/classes/main', 'RUN apk add --update tini python3 make g++ && rm -rf /var/cache/apk/*', 'WORKDIR /home/apprunner', 'COPY ./ ./', | ||
// https://stackoverflow.com/questions/33439230/how-to-write-commands-with-multiple-lines-in-dockerfile-while-preserving-the-new | ||
`RUN echo $'${this.sailorBuildGralde.replace(/\n/g, '\\n\\\n')}' > sailor_jvm_build.gradle`, `RUN ${this.isWrapperExists() ? './gradlew' : 'gradle'} clean prepareSailorWithDependencies -b ./sailor_jvm_build.gradle`, 'COPY ./component.json $CLASSES_MAIN_DIR'); | ||
return [ | ||
...gradle, | ||
...build, | ||
`FROM amazoncorretto:${this.getComponentRuntimeImage()}`, | ||
'ARG CLASSES_MAIN_DIR=./build/classes/main', | ||
'ARG RESOURCES_MAIN_DIR=./build/resources/main', | ||
'ARG DEPENDENCIES_DIR=./build/dependencies', | ||
'ENV CLASSPATH $CLASSES_MAIN_DIR:$RESOURCES_MAIN_DIR:$DEPENDENCIES_DIR/*', | ||
...this.getLabels(), | ||
'RUN addgroup -S apprunner && adduser -S apprunner -G apprunner -h /home/apprunner', | ||
'WORKDIR /home/apprunner', | ||
'USER apprunner', | ||
'COPY --from=build --chown=apprunner /home/apprunner/build /home/apprunner/build', | ||
'COPY --from=build --chown=apprunner /sbin/tini /sbin/tini', | ||
'ENTRYPOINT ["/sbin/tini", "-v", "-e", "143", "--"]' | ||
].join('\n'); | ||
} | ||
// TODO implement logic for gradle images after deprecation of appbuilder | ||
getComponentBuildImage() { | ||
return undefined; | ||
if (this.javaVersion === '1.8') { | ||
return `8-alpine-jdk`; | ||
} | ||
return `${this.javaVersion}-alpine-jdk`; | ||
} | ||
// TODO implement logic for gradle images after deprecation of appbuilder | ||
getComponentRuntimeImage() { | ||
return undefined; | ||
if (this.javaVersion === '1.8') { | ||
return `8-alpine-jre`; | ||
} | ||
return `${this.javaVersion}-alpine-jdk`; | ||
} | ||
/** | ||
* Load needed information from package.json and calculate needed nodejs version | ||
* Load needed information from build.gradle and calculate needed java version | ||
*/ | ||
@@ -107,4 +154,11 @@ async init() { | ||
if (!this.initialized) { | ||
// sailor gradle. used to download all dependencies as jars to | ||
// build/elasticio/dependencies/ folder | ||
this.sailorBuildGralde = (await fs_1.promises.readFile(`${path_1.default.resolve(__dirname, '../component/sailor_jvm_build.gradle')}`)) | ||
.toString(); | ||
// build.gradle is provided by component developer | ||
const buildGradle = await parser_1.default.parseText(context['build.gradle']); | ||
this.javaVersion = buildGradle.targetCompatibility || '1.8'; | ||
// TODO allow read version from buildGradle.targetCompatibility || buildGradle.sourceCompatibility | ||
// after generateDockerfile will support java versions >=11 | ||
this.javaVersion = '1.8'; | ||
this._sailorVersion = buildGradle.dependencies.find(item => item.name === 'sailor-jvm' && item.group === 'io.elastic').version; | ||
@@ -139,3 +193,6 @@ if (!this._sailorVersion) { | ||
this.checkInit(); | ||
return this.predefinedDockerfile || [ | ||
if (this.predefinedDockerfile) { | ||
return this.predefinedDockerfile; | ||
} | ||
return [ | ||
`FROM ${this.getComponentBuildImage()} AS base`, | ||
@@ -181,7 +238,7 @@ 'RUN apk add --update tini python3 make g++ && rm -rf /var/cache/apk/*', | ||
const result = await axios_1.default.get(this.nodejsDistUri); | ||
const allVersions = result.data.match(/[0-9]+\.[0-9]+\.[0-9]+/g) | ||
const allVersions = result.data.match(/\d+\.\d+\.\d+/g) | ||
.filter((version) => semver_1.default.gte(version, '0.8.6')) | ||
.sort((a, b) => semver_1.default.compare(a, b)); | ||
const stableVersions = result.data | ||
.match(/[0-9]+\.[0-9]*[02468]\.[0-9]+/g) | ||
.match(/\d+\.\d*[02468]\.\d+/g) | ||
.filter((version) => semver_1.default.gte(version, '0.8.6')) | ||
@@ -188,0 +245,0 @@ .sort((a, b) => semver_1.default.compare(a, b)); |
{ | ||
"name": "@elastic.io/component-build-helper", | ||
"version": "0.0.5-dev.12", | ||
"version": "0.0.5-dev.13", | ||
"description": "Helpers for the component build process", | ||
@@ -12,3 +12,4 @@ "main": "dist/src/index.js", | ||
"test": "mocha --config=./spec/.mocharc.js", | ||
"build": "tsc && chmod +x ./dist/src/cli.js", | ||
"build": "tsc", | ||
"postbuild": "chmod +x ./dist/src/cli.js && cp -r ./component ./dist/", | ||
"prepublishOnly": "npm run lint && npm run test" | ||
@@ -15,0 +16,0 @@ }, |
@@ -6,3 +6,3 @@ import sinon, { SinonSandbox } from 'sinon'; | ||
import { DockerfileGenerator } from '../../src/DockerfileGenerator'; | ||
import fs, { promises as fsPromise } from 'fs'; | ||
import fs, { promises as fsPromise, readFileSync } from 'fs'; | ||
import { ComponentContextLoader } from '../../src/ComponentContextLoader'; | ||
@@ -13,25 +13,11 @@ import { Readable } from 'stream'; | ||
componentJsonLabel, | ||
componentJsonTarLabel | ||
componentJsonTarLabel, | ||
gradleDockerfile, | ||
gradleWrapperDockerfile, labelsWithSplittedLogo, | ||
predefinedDockerfile | ||
} from '../fixtures/DockerfileGenerator.data'; | ||
const { expect } = chai; | ||
chai.use(require('sinon-chai')); | ||
const predefinedDockerfile = 'FROM node:15-alpine AS base\n' + | ||
'RUN apk add --update tini\n' + | ||
'WORKDIR /home/node\n' + | ||
'ADD --chown=node:node . ./\n' + | ||
'FROM base AS dependencies\n' + | ||
'ENV LOG_OUTPUT_MODE=long\n' + | ||
'USER node\n' + | ||
'RUN npm install\n' + | ||
'RUN npm test\n' + | ||
'RUN npm prune --production\n' + | ||
'RUN rm -rf spec* .circleci README.md LICENSE\n' + | ||
'FROM node:15-alpine AS release\n' + | ||
'WORKDIR /home/node\n' + | ||
'COPY --from=base --chown=node:node /sbin/tini /sbin/tini\n' + | ||
'COPY --from=dependencies --chown=node:node /home/node /home/node\n' + | ||
'USER node\n' + | ||
'ENTRYPOINT ["/sbin/tini", "-v", "-e", "143", "--"]\n'; | ||
describe('DockerfileGenerator', function () { | ||
@@ -42,4 +28,6 @@ let sandbox: SinonSandbox; | ||
let logo: string; | ||
let bigLogo: string; | ||
let componentContextLoader: ComponentContextLoader; | ||
before(async () => { | ||
bigLogo = readFileSync('./spec/fixtures/component/big-logo.png').toString('base64'); | ||
nodeVersions = (await fsPromise.readFile('./spec/fixtures/nodeVersions.html')).toString(); | ||
@@ -54,36 +42,37 @@ logo = (await fsPromise.readFile('./spec/fixtures/component/nodejs/logo.png')).toString('base64'); | ||
describe('newInstance', () => { | ||
it('should throw an error in case unknown component type', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/'); | ||
await expect(DockerfileGenerator.getInstance(componentContextLoader)) | ||
.to.be.rejectedWith('Unknown sources type. Please make sure that you provided correct component sources'); | ||
}); | ||
it('should properly get version from semver.io', async () => { | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
.get('/dist/') | ||
.reply(200, nodeVersions, [ | ||
'Content-Type', | ||
'text/html' | ||
]); | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs/'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
expect(dockerfileGenerator['getComponentBuildImage']()).to.be.equal('node:16-alpine'); | ||
}); | ||
it('should return LTS version gin case engine is not specified', async () => { | ||
sandbox.stub(fsPromise, 'readFile').resolves(Buffer.from('{ "dependencies": { "elasticio-sailor-nodejs": "2.2.2"} }')); | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
.get('/dist/') | ||
.reply(200, nodeVersions, [ | ||
'Content-Type', | ||
'text/html' | ||
]); | ||
expect(dockerfileGenerator['getComponentBuildImage']()).to.be.equal('node:18-alpine'); | ||
}); | ||
it('should throw an error in case unknown component type', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/'); | ||
await expect(DockerfileGenerator.getInstance(componentContextLoader)) | ||
.to.be.rejectedWith('Unknown sources type. Please make sure that you provided correct component sources'); | ||
}); | ||
describe('NodeJsDockerfile', () => { | ||
describe('node version', () => { | ||
it('should properly get version from semver.io', async () => { | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
.get('/dist/') | ||
.reply(200, nodeVersions, [ | ||
'Content-Type', | ||
'text/html' | ||
]); | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs/'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
expect(dockerfileGenerator['getComponentBuildImage']()).to.be.equal('node:16-alpine'); | ||
}); | ||
it('should return LTS version gin case engine is not specified', async () => { | ||
sandbox.stub(fsPromise, 'readFile').resolves(Buffer.from('{ "dependencies": { "elasticio-sailor-nodejs": "2.2.2"} }')); | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
.get('/dist/') | ||
.reply(200, nodeVersions, [ | ||
'Content-Type', | ||
'text/html' | ||
]); | ||
expect(dockerfileGenerator['getComponentBuildImage']()).to.be.equal('node:18-alpine'); | ||
}); | ||
}); | ||
describe('genDockerfile from directory', () => { | ||
it('genDockerfile should return dockerfile structure', async () => { | ||
beforeEach(() => { | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
@@ -95,2 +84,4 @@ .get('/dist/') | ||
]); | ||
}); | ||
it('genDockerfile should return dockerfile structure', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs'); | ||
@@ -113,3 +104,3 @@ dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
`LABEL elastic.io.component=${JSON.stringify(JSON.stringify(componentJsonLabel))}\n` + | ||
`LABEL elastic.io.logo=${logo}\n` + | ||
`LABEL elastic.io.logo="${logo}"\n` + | ||
'WORKDIR /home/node\n' + | ||
@@ -126,8 +117,2 @@ 'COPY --from=base --chown=node:node /sbin/tini /sbin/tini\n' + | ||
readFileStub.callThrough(); | ||
nock('https://nodejs.org:443', { 'encodedQueryParams': true }) | ||
.get('/dist/') | ||
.reply(200, nodeVersions, [ | ||
'Content-Type', | ||
'text/html' | ||
]); | ||
componentContextLoader = await ComponentContextLoader.getInstance(path); | ||
@@ -137,3 +122,3 @@ dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
`\nLABEL elastic.io.component=${JSON.stringify(JSON.stringify(componentJsonLabel))}\n` + | ||
`LABEL elastic.io.logo=${logo}`); | ||
`LABEL elastic.io.logo="${logo}"`); | ||
}); | ||
@@ -170,3 +155,3 @@ }); | ||
`LABEL elastic.io.component=${JSON.stringify(JSON.stringify(componentJsonTarLabel))}\n` + | ||
`LABEL elastic.io.logo=${logo}\n` + | ||
`LABEL elastic.io.logo="${logo}"\n` + | ||
'WORKDIR /home/node\n' + | ||
@@ -190,6 +175,15 @@ 'COPY --from=base --chown=node:node /sbin/tini /sbin/tini\n' + | ||
`\nLABEL elastic.io.component=${JSON.stringify(JSON.stringify(componentJsonTarLabel))}\n` + | ||
`LABEL elastic.io.logo=${logo}`); | ||
`LABEL elastic.io.logo="${logo}"`); | ||
}); | ||
}); | ||
it('should split long lines in the dockerfile labels', async () => { | ||
const readFileStub = sandbox.stub(fsPromise, 'readFile'); | ||
readFileStub.withArgs(`./spec/fixtures/component/nodejs/logo.png`).resolves(bigLogo); | ||
readFileStub.callThrough(); | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/nodejs'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
expect(dockerfileGenerator['getLabels']()).to.deep.eq(labelsWithSplittedLogo); | ||
}); | ||
describe('resolveRange', () => { | ||
@@ -234,9 +228,16 @@ let componentContextLoader: ComponentContextLoader; | ||
describe('genDockerfile from directory', () => { | ||
it('should install gradle in the dockerfile in case wrapper is not exists', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/gradle'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
expect(dockerfileGenerator.genDockerfile()).to.be.equal(gradleDockerfile); | ||
}); | ||
it('should use gradlew in the dockerfile', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/gradle-wrapper'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
expect(dockerfileGenerator.genDockerfile()).to.be.equal(gradleWrapperDockerfile); | ||
}); | ||
it('genDockerfile should return dockerfile structure', async () => { | ||
componentContextLoader = await ComponentContextLoader.getInstance('./spec/fixtures/component/gradle'); | ||
dockerfileGenerator = await DockerfileGenerator.getInstance(componentContextLoader); | ||
await expect(dockerfileGenerator.genDockerfile()).to.be.equal('FROM elasticio/apprunner:production\n' + | ||
'ADD ./ /home/apprunner\n' + | ||
`LABEL elastic.io.component=${JSON.stringify(componentJsonGradleLabel)}\n` + | ||
`LABEL elastic.io.logo=${logo}`); | ||
expect(dockerfileGenerator.genDockerfile()).to.be.equal(gradleDockerfile); | ||
}); | ||
@@ -252,3 +253,3 @@ it('genDockerfile should return predefined dockerfile with labels', async () => { | ||
`\nLABEL elastic.io.component=${JSON.stringify(componentJsonGradleLabel)}\n` + | ||
`LABEL elastic.io.logo=${logo}`); | ||
`LABEL elastic.io.logo="${logo}"`); | ||
}); | ||
@@ -255,0 +256,0 @@ }); |
@@ -10,3 +10,4 @@ /// <reference types="node" /> | ||
interface GradleFile { | ||
targetCompatibility: string; | ||
targetCompatibility: '1.8' | '11' | '17'; | ||
sourceCompatibility: '1.8' | '11' | '17'; | ||
dependencies: Dependency[]; | ||
@@ -13,0 +14,0 @@ } |
@@ -18,2 +18,4 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ | ||
'build.gradle', | ||
'gradlew', | ||
// Common | ||
'component.json', | ||
@@ -20,0 +22,0 @@ 'Dockerfile', |
@@ -8,3 +8,4 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ | ||
import g2js from 'gradle-to-js/lib/parser'; | ||
import { promises as fs } from 'fs'; | ||
import path from 'path'; | ||
export abstract class DockerfileGenerator { | ||
@@ -77,7 +78,18 @@ protected _componentLanguage: COMPONENT_LANGUAGE; | ||
// need to stringify 2 times to get escaped json string | ||
`LABEL elastic.io.component=${JSON.stringify(JSON.stringify(this.componentJson))}`, | ||
`LABEL elastic.io.logo=${this._icon}` | ||
`LABEL elastic.io.component=${this.prepareLabel(JSON.stringify(JSON.stringify(this.componentJson)))}`, | ||
`LABEL elastic.io.logo="${this.prepareLabel(this._icon)}"` | ||
]; | ||
} | ||
// dockerfile line can not be greater than max allowed size of 65535 | ||
// So just split long labels to lines with such size | ||
protected prepareLabel(str: string, chunkSize = 65500) { | ||
const chunks = []; | ||
for (let i = 0; i < str.length; i += chunkSize) { | ||
const chunk = str.slice(i, i + chunkSize); | ||
chunks.push(chunk); | ||
} | ||
return chunks.join('\\\n'); | ||
} | ||
// Developer can specify custom dockerfile for component. | ||
@@ -95,3 +107,5 @@ // We need to add labels in such cases | ||
export class GradleDockerfileGenerator extends DockerfileGenerator { | ||
private javaVersion: string; | ||
readonly defaultGradleVersion = '7.4.2'; | ||
private javaVersion: '1.8' | '11' | '17'; | ||
private sailorBuildGralde: string; | ||
@@ -109,23 +123,78 @@ constructor(componentContextLoader: ComponentContextLoader) { | ||
// TODO use apprunner for now. implement new dockerfile structure for gradle components | ||
private isWrapperExists() { | ||
return this.componentContextLoader.context['gradlew']; | ||
} | ||
genDockerfile() { | ||
return this.predefinedDockerfile || [ | ||
'FROM elasticio/apprunner:production', | ||
'ADD ./ /home/apprunner', | ||
...this.getLabels() | ||
this.checkInit(); | ||
if (this.predefinedDockerfile) { | ||
return this.predefinedDockerfile; | ||
} | ||
const gradle = []; | ||
const build = []; | ||
if (!this.isWrapperExists()) { | ||
// installing gradle, because wrapper is not exists in the component | ||
gradle.push( | ||
`FROM amazoncorretto:${this.getComponentBuildImage()} as gradle`, | ||
`ARG GRADLE_VERSION=${this.defaultGradleVersion}`, | ||
'ENV GRADLE_ARCHIVE gradle-$GRADLE_VERSION-bin.zip', | ||
'WORKDIR /opt', | ||
'RUN apk update && apk add --no-cache wget libstdc++ && rm -rf /var/cache/apk/*', | ||
'RUN wget --no-verbose https://services.gradle.org/distributions/$GRADLE_ARCHIVE', | ||
'RUN unzip -q $GRADLE_ARCHIVE && rm $GRADLE_ARCHIVE', | ||
'ENV PATH "$PATH:/opt/gradle-$GRADLE_VERSION/bin/"' | ||
); | ||
build.push( | ||
'FROM gradle as build' | ||
); | ||
} else { | ||
build.push( | ||
`FROM amazoncorretto:${this.getComponentBuildImage()} as build` | ||
); | ||
} | ||
build.push( | ||
'ARG CLASSES_MAIN_DIR=./build/classes/main', | ||
'RUN apk add --update tini python3 make g++ && rm -rf /var/cache/apk/*', | ||
'WORKDIR /home/apprunner', | ||
'COPY ./ ./', | ||
// https://stackoverflow.com/questions/33439230/how-to-write-commands-with-multiple-lines-in-dockerfile-while-preserving-the-new | ||
`RUN echo $'${this.sailorBuildGralde.replace(/\n/g, '\\n\\\n')}' > sailor_jvm_build.gradle`, | ||
`RUN ${this.isWrapperExists() ? './gradlew' : 'gradle'} clean prepareSailorWithDependencies -b ./sailor_jvm_build.gradle`, | ||
'COPY ./component.json $CLASSES_MAIN_DIR' | ||
); | ||
return [ | ||
...gradle, | ||
...build, | ||
`FROM amazoncorretto:${this.getComponentRuntimeImage()}`, | ||
'ARG CLASSES_MAIN_DIR=./build/classes/main', | ||
'ARG RESOURCES_MAIN_DIR=./build/resources/main', | ||
'ARG DEPENDENCIES_DIR=./build/dependencies', | ||
'ENV CLASSPATH $CLASSES_MAIN_DIR:$RESOURCES_MAIN_DIR:$DEPENDENCIES_DIR/*', | ||
...this.getLabels(), | ||
'RUN addgroup -S apprunner && adduser -S apprunner -G apprunner -h /home/apprunner', | ||
'WORKDIR /home/apprunner', | ||
'USER apprunner', | ||
'COPY --from=build --chown=apprunner /home/apprunner/build /home/apprunner/build', | ||
'COPY --from=build --chown=apprunner /sbin/tini /sbin/tini', | ||
'ENTRYPOINT ["/sbin/tini", "-v", "-e", "143", "--"]' | ||
].join('\n'); | ||
} | ||
// TODO implement logic for gradle images after deprecation of appbuilder | ||
getComponentBuildImage(): Promise<string> | string { | ||
return undefined; | ||
if (this.javaVersion === '1.8') { | ||
return `8-alpine-jdk`; | ||
} | ||
return `${this.javaVersion}-alpine-jdk`; | ||
} | ||
// TODO implement logic for gradle images after deprecation of appbuilder | ||
getComponentRuntimeImage(): Promise<string> | string { | ||
return undefined; | ||
if (this.javaVersion === '1.8') { | ||
return `8-alpine-jre`; | ||
} | ||
return `${this.javaVersion}-alpine-jdk`; | ||
} | ||
/** | ||
* Load needed information from package.json and calculate needed nodejs version | ||
* Load needed information from build.gradle and calculate needed java version | ||
*/ | ||
@@ -135,5 +204,13 @@ public async init() { | ||
if (!this.initialized) { | ||
// sailor gradle. used to download all dependencies as jars to | ||
// build/elasticio/dependencies/ folder | ||
this.sailorBuildGralde = (await fs.readFile(`${path.resolve(__dirname, '../component/sailor_jvm_build.gradle')}`)) | ||
.toString(); | ||
// build.gradle is provided by component developer | ||
const buildGradle = await g2js.parseText(context['build.gradle']); | ||
this.javaVersion = buildGradle.targetCompatibility || '1.8'; | ||
this._sailorVersion = buildGradle.dependencies.find(item => item.name === 'sailor-jvm' && item.group === 'io.elastic').version; | ||
// TODO allow read version from buildGradle.targetCompatibility || buildGradle.sourceCompatibility | ||
// after generateDockerfile will support java versions >=11 | ||
this.javaVersion = '1.8'; | ||
this._sailorVersion = buildGradle.dependencies.find(item => | ||
item.name === 'sailor-jvm' && item.group === 'io.elastic').version; | ||
if (!this._sailorVersion) { | ||
@@ -173,3 +250,6 @@ throw new Error('Can not find "sailor-jvm" dependency.'); | ||
this.checkInit(); | ||
return this.predefinedDockerfile || [ | ||
if (this.predefinedDockerfile) { | ||
return this.predefinedDockerfile; | ||
} | ||
return [ | ||
`FROM ${this.getComponentBuildImage()} AS base`, | ||
@@ -217,3 +297,3 @@ 'RUN apk add --update tini python3 make g++ && rm -rf /var/cache/apk/*', | ||
const result = await axios.get(this.nodejsDistUri); | ||
const allVersions = result.data.match(/[0-9]+\.[0-9]+\.[0-9]+/g) | ||
const allVersions = result.data.match(/\d+\.\d+\.\d+/g) | ||
.filter((version: string) => semver.gte(version, '0.8.6')) | ||
@@ -223,3 +303,3 @@ .sort((a: string, b: string) => semver.compare(a, b)); | ||
const stableVersions = result.data | ||
.match(/[0-9]+\.[0-9]*[02468]\.[0-9]+/g) | ||
.match(/\d+\.\d*[02468]\.\d+/g) | ||
.filter((version: string) => semver.gte(version, '0.8.6')) | ||
@@ -226,0 +306,0 @@ .sort((a: string, b: string) => semver.compare(a, b)); |
@@ -27,4 +27,4 @@ { | ||
"src/**/*", | ||
"resources/**/*", | ||
"resources/**/*" | ||
] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
746640
74
3207
6