From afbd752a299952da766ba4060237fe0da411b6c1 Mon Sep 17 00:00:00 2001 From: sebastianbarrozo Date: Mon, 11 Nov 2024 12:39:56 -0300 Subject: [PATCH 1/4] Issue #42: Remove log output ETP-729 --- .../ResolverDependencyLoader.groovy | 83 +++++++++---------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy b/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy index dde3261..19adee1 100644 --- a/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy +++ b/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy @@ -81,52 +81,58 @@ class ResolverDependencyLoader { // see https://github.com/gradle/gradle/issues/11914 for more info def antClassLoader = org.apache.tools.ant.Project.class.classLoader List dependencies = [] - List files = [] // /** * aux ant path used to hold gradle jar files */ - File destDirectory = new File(sourcePath, "./build/lib/runtime") + final String LIB_DIR = 'lib' + File destDirectory = new File(project.buildDir, LIB_DIR) destDirectory.mkdirs() - jarFiles.each { + jarFiles.each { File jarFile -> // Copy the jar to the runtime directory - File destFile = new File(destDirectory, it.name) - Files.copy(it.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING) - files.add("./" + it.getName()) - // Add the jar to the ant path to be used to create WebContent - dependencies.add(it.absolutePath) + dependencies.add(jarFile.absolutePath) + } + List files = dependencies + final List DIRS = [ + new File("${project.rootDir.absolutePath}/lib"), + new File("${project.rootDir.absolutePath}/modules"), + new File("${project.rootDir.absolutePath}/modules_core"), + ] + DIRS.each { File dir -> + if (dir.exists()) { + FileTree libFiles = project.fileTree(dir).include('**/*.jar') as FileTree + // Search recursively for all jars in the lib directory and add to classpath jar + libFiles.each { File lib -> + files.add(lib.absolutePath) + } + } + } + final String CLASSPATH_JAR_NAME = 'classpath.jar' + final String CLASSPATH_JAR_ABSOLUTE_PATH = "${destDirectory.absolutePath}/${CLASSPATH_JAR_NAME}" + final String CLASSPATH_SEPARATOR = ' ' + String strClasspath = '' + files.forEach { String file -> + if (OperatingSystem.current().isWindows()) { + // Windows paths need to be file:/// and replace \ with / + strClasspath += 'file:///' + file.toString().replaceAll('\\\\', '/') + CLASSPATH_SEPARATOR + } else { + strClasspath += file.toString() + CLASSPATH_SEPARATOR + } } - def classpathJarName = "classpath.jar"; // CREATE JAR HERE FROM gradle.custom and create a Manifest with the classpath - project.ant.jar(destfile: "${destDirectory.absolutePath}/${classpathJarName}") { + project.ant.jar(destfile: CLASSPATH_JAR_ABSOLUTE_PATH) { manifest { - attribute(name: "Class-Path", value: files.join(' ')) + attribute(name: 'Class-Path', value: strClasspath) } } - project.ant.path(id:'gradle.custom') - project.ant.references['gradle.custom'].add(project.ant.path(location: new File(destDirectory.absolutePath, classpathJarName))) - - /** - * Creates an Ant property with the value of the gradle Jar paths. - * Ex: '/path/to/jar0:/path/to/jar1/' - * - * This is used when the project loads the Ant file - * to pass the Gradle libs classpath (dependencies defined with 'implementation'). - * - * This is a workaround to the problem when an Ant target calls another target with '' - * and the Gradle classpath is not being recognized. - * - * When a target uses the 'depends' value pointing to another Ant target there is no problem. - * should be avoided. - * - * Also sometimes when Ant calls forked classes, the Ant references 'refid' defined by Gradle will be lost. - * To prevents 'refid' errors a property with 'value' is used. - * - */ - project.ant.properties['gradle.custom.dependencies'] = project.ant.references['gradle.custom'].toString() - - project.ant.project.setProperty("env.GRADLE_CLASSPATH", project.ant.references['gradle.custom'].toString()) + project.ant.property(name: 'base.lib', location: new File("${project.rootDir}/build", LIB_DIR)) + // + final String GRADE_CUSTOM = 'gradle.custom' + project.ant.path(id: GRADE_CUSTOM) + project.ant.references[GRADE_CUSTOM].add(project.ant.path(location: CLASSPATH_JAR_ABSOLUTE_PATH)) + project.ant.properties['gradle.custom.dependencies'] = project.ant.references[GRADE_CUSTOM].toString() + project.ant.project.setProperty('env.GRADLE_CLASSPATH', project.ant.references[GRADE_CUSTOM].toString()) // This gets all dependencies and sets them in ant as a file list with id: "gradle.libs" // Ant task build.local.context uses this to copy them to WebContent @@ -137,13 +143,4 @@ class ResolverDependencyLoader { } - static String getSourcePath() { - def propsFile = new File("config/Openbravo.properties") - def props = new Properties() - if(!propsFile.exists()) { - return "." - } - props.load(propsFile.newReader()) - return props.getProperty("source.path") - } } From c9fd433615fa276cd9698080d20b6f6a172665ac Mon Sep 17 00:00:00 2001 From: sebastianbarrozo Date: Mon, 11 Nov 2024 13:03:14 -0300 Subject: [PATCH 2/4] Issue #42: Format file ETP-729 --- .../ResolverDependencyLoader.groovy | 238 +++++++++--------- 1 file changed, 115 insertions(+), 123 deletions(-) diff --git a/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy b/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy index 19adee1..af5d1c6 100644 --- a/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy +++ b/src/main/groovy/com/etendoerp/legacy/dependencies/ResolverDependencyLoader.groovy @@ -9,138 +9,130 @@ import com.etendoerp.legacy.utils.GithubUtils import com.etendoerp.modules.ModulesConfigurationUtils import com.etendoerp.publication.configuration.PublicationConfiguration import org.gradle.api.Project -import org.gradle.api.logging.LogLevel -import java.nio.file.Files -import java.nio.file.StandardCopyOption import org.gradle.api.file.FileTree import org.gradle.internal.os.OperatingSystem -import org.gradle.api.logging.LogLevel -import java.nio.file.Files -import java.nio.file.StandardCopyOption class ResolverDependencyLoader { - final static String CONSISTENCY_CONTAINER = "CONSISTENCY_CONTAINER" + final static String CONSISTENCY_CONTAINER = "CONSISTENCY_CONTAINER" - static load(Project project) { + static load(Project project) { - // Configuration container used to store all project and subproject dependencies - project.configurations { - etendoDependencyContainer - } + // Configuration container used to store all project and subproject dependencies + project.configurations { + etendoDependencyContainer + } - /** - * This method gets all resolved dependencies by gradle and pass all resolved jars to ANT tasks - */ - - project.afterEvaluate { - project.logger.info("Running GRADLE projectsEvaluated.") - - if (project.state.failure) { - project.logger.error("* ERROR: ${project.state.failure.getMessage()}") - project.state.failure.printStackTrace() - return - } - - GithubUtils.configureRepositories(project) - CoreMetadata coreMetadata = new CoreMetadata(project) - - ModulesConfigurationUtils.configureSubprojects(project) - - PublicationConfiguration publicationConfiguration = new PublicationConfiguration(project) - publicationConfiguration.configurePublication() - - EtendoArtifactsConsistencyContainer consistencyContainer = new EtendoArtifactsConsistencyContainer(project, coreMetadata) - consistencyContainer.loadInstalledArtifacts() - - // Save the consistency container in the project - project.ext.set(CONSISTENCY_CONTAINER, consistencyContainer) - - def extension = project.extensions.findByType(EtendoPluginExtension) - boolean loadCompilationDependencies = extension.loadCompilationDependencies - boolean loadTestDependencies = extension.loadTestDependencies - - // Load Etendo core compilation dependencies when the core is in jar - if (loadCompilationDependencies) { - EtendoCoreDependencies.loadCoreCompilationDependencies(project) - } - - // Load Etendo core test dependencies - if (loadTestDependencies) { - EtendoCoreDependencies.loadCoreTestDependencies(project) - } - - DependencyProcessor dependencyProcessor = new DependencyProcessor(project, coreMetadata) - List jarFiles = dependencyProcessor.processJarFiles() - - // Note: previously the antClassLoader was used to add classes to ant's classpath - // but when the core is a complete jar (with libs) affecting the class loader can cause collisions - // (for example, the IOFileFilter of apache commons appears in the core jar and the gradle libs) - // Since the defined ant tasks specify a classpath, the code below should be enough - // otherwise doing a antClassLoader.addURL for each dependency will bring back the previous behaviour, but it will cause problems - // see https://github.com/gradle/gradle/issues/11914 for more info - def antClassLoader = org.apache.tools.ant.Project.class.classLoader - List dependencies = [] - // - - /** - * aux ant path used to hold gradle jar files - */ - final String LIB_DIR = 'lib' - File destDirectory = new File(project.buildDir, LIB_DIR) - destDirectory.mkdirs() - jarFiles.each { File jarFile -> - // Copy the jar to the runtime directory - dependencies.add(jarFile.absolutePath) - } - List files = dependencies - final List DIRS = [ - new File("${project.rootDir.absolutePath}/lib"), - new File("${project.rootDir.absolutePath}/modules"), - new File("${project.rootDir.absolutePath}/modules_core"), - ] - DIRS.each { File dir -> - if (dir.exists()) { - FileTree libFiles = project.fileTree(dir).include('**/*.jar') as FileTree - // Search recursively for all jars in the lib directory and add to classpath jar - libFiles.each { File lib -> - files.add(lib.absolutePath) - } - } - } - final String CLASSPATH_JAR_NAME = 'classpath.jar' - final String CLASSPATH_JAR_ABSOLUTE_PATH = "${destDirectory.absolutePath}/${CLASSPATH_JAR_NAME}" - final String CLASSPATH_SEPARATOR = ' ' - String strClasspath = '' - files.forEach { String file -> - if (OperatingSystem.current().isWindows()) { - // Windows paths need to be file:/// and replace \ with / - strClasspath += 'file:///' + file.toString().replaceAll('\\\\', '/') + CLASSPATH_SEPARATOR - } else { - strClasspath += file.toString() + CLASSPATH_SEPARATOR - } - } - // CREATE JAR HERE FROM gradle.custom and create a Manifest with the classpath - project.ant.jar(destfile: CLASSPATH_JAR_ABSOLUTE_PATH) { - manifest { - attribute(name: 'Class-Path', value: strClasspath) - } - } - project.ant.property(name: 'base.lib', location: new File("${project.rootDir}/build", LIB_DIR)) - // - final String GRADE_CUSTOM = 'gradle.custom' - project.ant.path(id: GRADE_CUSTOM) - project.ant.references[GRADE_CUSTOM].add(project.ant.path(location: CLASSPATH_JAR_ABSOLUTE_PATH)) - project.ant.properties['gradle.custom.dependencies'] = project.ant.references[GRADE_CUSTOM].toString() - project.ant.project.setProperty('env.GRADLE_CLASSPATH', project.ant.references[GRADE_CUSTOM].toString()) - - // This gets all dependencies and sets them in ant as a file list with id: "gradle.libs" - // Ant task build.local.context uses this to copy them to WebContent - project.ant.filelist(id: 'gradle.libs', files: dependencies.join(',')) - - AntLoader.loadAntFile(project, coreMetadata) + /** + * This method gets all resolved dependencies by gradle and pass all resolved jars to ANT tasks + */ + + project.afterEvaluate { + project.logger.info("Running GRADLE projectsEvaluated.") + + if (project.state.failure) { + project.logger.error("* ERROR: ${project.state.failure.getMessage()}") + project.state.failure.printStackTrace() + return + } + + GithubUtils.configureRepositories(project) + CoreMetadata coreMetadata = new CoreMetadata(project) + + ModulesConfigurationUtils.configureSubprojects(project) + + PublicationConfiguration publicationConfiguration = new PublicationConfiguration(project) + publicationConfiguration.configurePublication() + + EtendoArtifactsConsistencyContainer consistencyContainer = new EtendoArtifactsConsistencyContainer(project, coreMetadata) + consistencyContainer.loadInstalledArtifacts() + + // Save the consistency container in the project + project.ext.set(CONSISTENCY_CONTAINER, consistencyContainer) + + def extension = project.extensions.findByType(EtendoPluginExtension) + boolean loadCompilationDependencies = extension.loadCompilationDependencies + boolean loadTestDependencies = extension.loadTestDependencies + + // Load Etendo core compilation dependencies when the core is in jar + if (loadCompilationDependencies) { + EtendoCoreDependencies.loadCoreCompilationDependencies(project) + } + + // Load Etendo core test dependencies + if (loadTestDependencies) { + EtendoCoreDependencies.loadCoreTestDependencies(project) + } + + DependencyProcessor dependencyProcessor = new DependencyProcessor(project, coreMetadata) + List jarFiles = dependencyProcessor.processJarFiles() + + // Note: previously the antClassLoader was used to add classes to ant's classpath + // but when the core is a complete jar (with libs) affecting the class loader can cause collisions + // (for example, the IOFileFilter of apache commons appears in the core jar and the gradle libs) + // Since the defined ant tasks specify a classpath, the code below should be enough + // otherwise doing a antClassLoader.addURL for each dependency will bring back the previous behaviour, but it will cause problems + // see https://github.com/gradle/gradle/issues/11914 for more info + def antClassLoader = org.apache.tools.ant.Project.class.classLoader + List dependencies = [] + /** + * aux ant path used to hold gradle jar files + */ + final String LIB_DIR = 'lib' + File destDirectory = new File(project.buildDir, LIB_DIR) + destDirectory.mkdirs() + jarFiles.each { File jarFile -> + // Copy the jar to the runtime directory + dependencies.add(jarFile.absolutePath) + } + List files = dependencies + final List DIRS = [ + new File("${project.rootDir.absolutePath}/lib"), + new File("${project.rootDir.absolutePath}/modules"), + new File("${project.rootDir.absolutePath}/modules_core"), + ] + DIRS.each { File dir -> + if (dir.exists()) { + FileTree libFiles = project.fileTree(dir).include('**/*.jar') as FileTree + // Search recursively for all jars in the lib directory and add to classpath jar + libFiles.each { File lib -> + files.add(lib.absolutePath) + } } - + } + final String CLASSPATH_JAR_NAME = 'classpath.jar' + final String CLASSPATH_JAR_ABSOLUTE_PATH = "${destDirectory.absolutePath}/${CLASSPATH_JAR_NAME}" + final String CLASSPATH_SEPARATOR = ' ' + String strClasspath = '' + files.forEach { String file -> + if (OperatingSystem.current().isWindows()) { + // Windows paths need to be file:/// and replace \ with / + strClasspath += 'file:///' + file.toString().replaceAll('\\\\', '/') + CLASSPATH_SEPARATOR + } else { + strClasspath += file.toString() + CLASSPATH_SEPARATOR + } + } + // CREATE JAR HERE FROM gradle.custom and create a Manifest with the classpath + project.ant.jar(destfile: CLASSPATH_JAR_ABSOLUTE_PATH) { + manifest { + attribute(name: 'Class-Path', value: strClasspath) + } + } + project.ant.property(name: 'base.lib', location: new File("${project.rootDir}/build", LIB_DIR)) + // + final String GRADE_CUSTOM = 'gradle.custom' + project.ant.path(id: GRADE_CUSTOM) + project.ant.references[GRADE_CUSTOM].add(project.ant.path(location: CLASSPATH_JAR_ABSOLUTE_PATH)) + project.ant.properties['gradle.custom.dependencies'] = project.ant.references[GRADE_CUSTOM].toString() + project.ant.project.setProperty('env.GRADLE_CLASSPATH', project.ant.references[GRADE_CUSTOM].toString()) + + // This gets all dependencies and sets them in ant as a file list with id: "gradle.libs" + // Ant task build.local.context uses this to copy them to WebContent + project.ant.filelist(id: 'gradle.libs', files: dependencies.join(',')) + + AntLoader.loadAntFile(project, coreMetadata) } + } + } From 159edbf3bd7b959e873ee27c503329b5fdfe656d Mon Sep 17 00:00:00 2001 From: Valeria Garcia Date: Mon, 11 Nov 2024 20:34:07 +0000 Subject: [PATCH 3/4] Feature ETP-732: Add pipeline for test Etendo compilation Add Github credentials vars in gradle.properties.template. Add Git Police Action. --- .github/workflows/auto-reviewer.yml | 19 +- .github/workflows/git-police.yml | 49 ++++ gradle.properties.template | 8 +- pipelines/JenkinsFileTestCompile | 388 ++++++++++++++++++++++++++++ pipelines/build-update.sh | 18 -- pipelines/utils/build-update.sh | 19 ++ pipelines/utils/infoCommits.groovy | 48 ++++ 7 files changed, 523 insertions(+), 26 deletions(-) create mode 100644 .github/workflows/git-police.yml create mode 100644 pipelines/JenkinsFileTestCompile delete mode 100644 pipelines/build-update.sh create mode 100755 pipelines/utils/build-update.sh create mode 100755 pipelines/utils/infoCommits.groovy diff --git a/.github/workflows/auto-reviewer.yml b/.github/workflows/auto-reviewer.yml index 6bbbc01..674bb7b 100644 --- a/.github/workflows/auto-reviewer.yml +++ b/.github/workflows/auto-reviewer.yml @@ -1,15 +1,16 @@ name: Auto Reviewer on: - pull_request: - types: [opened, reopened, synchronize] + workflow_run: + workflows: [Git Police] + types: + - completed jobs: make-review: - if: github.head_ref != 'develop' + if: github.head_ref != 'develop' && github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest env: - PULL_REQUEST: ${{ github.event.pull_request.number }} PROJECT: ${{ github.event.repository.owner.login }} REPO_SLUG: ${{ github.event.repository.name }} OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} @@ -20,6 +21,14 @@ jobs: - name: Checkout code uses: actions/checkout@v2 + - name: Fetch pull request number + id: fetch-pr + run: | + PR_NUMBER=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://api.github.com/repos/${{ env.PROJECT }}/${{ env.REPO_SLUG }}/pulls?head=${{ env.PROJECT }}:${{ github.head_ref }}" \ + | jq '.[0].number') + echo "PULL_REQUEST=$PR_NUMBER" >> $GITHUB_ENV + - name: Run Docker container id: run-docker run: | @@ -27,6 +36,7 @@ jobs: echo "-------------------------------------------------------------------------" echo ${{ env.DOCKERHUB_PASSWORD }} | docker login --username "${{ env.DOCKERHUB_USERNAME }}" --password-stdin docker run -d -p 5000:5000 -e REPO_API_TOKEN="${{ env.ETENDOBOT_TOKEN }}" -e PULL_REQUEST=${{ env.PULL_REQUEST }} -e PROJECT=${{ env.PROJECT }} -e REPO_SLUG=${{ env.REPO_SLUG }} -e OPENAI_API_KEY="${{ env.OPENAI_API_KEY }}" etendo/code-reviewer:latest + - name: Make Reviewer API call id: call-api run: | @@ -34,7 +44,6 @@ jobs: response=$(curl -s -o response.txt -w "%{http_code}" -X GET http://localhost:5000/review/github) if [ $response -ne 200 ]; then echo "API call failed with status code $response. This is likely an error related to the PR data, or an internal API error" - echo "Response text:" cat response.txt exit 1 diff --git a/.github/workflows/git-police.yml b/.github/workflows/git-police.yml new file mode 100644 index 0000000..7878651 --- /dev/null +++ b/.github/workflows/git-police.yml @@ -0,0 +1,49 @@ +name: Git Police + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + git-police: + name: Git Police + if: github.head_ref != 'develop' + runs-on: ubuntu-latest + env: + PR_ID: ${{ github.event.pull_request.number }} + REPO_NAME: ${{ github.event.repository.name }} + ETENDOBOT_TOKEN: ${{ secrets.ETENDOBOT_TOKEN }} + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run Docker container + id: run-docker + run: | + printenv + echo "-------------------------------------------------------------------------" + echo ${{ env.DOCKERHUB_PASSWORD }} | docker login --username "${{ env.DOCKERHUB_USERNAME }}" --password-stdin + docker run -d -p 5000:5000 -e REPO_TOKEN="${{ env.ETENDOBOT_TOKEN }}" -e PR_ID=${{ env.PR_ID }} -e REPO_NAME=${{ env.REPO_NAME }} etendo/gitpolice:latest + - name: Git Police API call + id: call-api + run: | + sleep 10s + response=$(curl -s -o response.txt -w "%{http_code}" -X GET http://localhost:5000/api/github) + if [ $response -ne 200 ]; then + echo "API call failed with status code $response. This is likely an error related to the PR data, or an internal API error" + + echo "Response text:" + cat response.txt + exit 1 + fi + if ! grep -q "Valid branch name and correct destination" response.txt; then + echo "Git Police check failed: response does not contain 'Valid branch name and correct destination'" + echo "Full response:" + cat response.txt + exit 1 + fi + echo "API call successful with status code $response" + echo "Response text" + cat response.txt diff --git a/gradle.properties.template b/gradle.properties.template index c0b5887..4f5bdf4 100644 --- a/gradle.properties.template +++ b/gradle.properties.template @@ -1,5 +1,7 @@ -nexusUser = "" -nexusPassword = "" +nexusUser= +nexusPassword= +githubUser= +githubToken= test.bbdd.url= test.bbdd.sid= @@ -8,4 +10,4 @@ test.bbdd.systemPassword= test.bbdd.user= test.bbdd.password= org.gradle.daemon=false -org.gradle.jvmargs=-Xmx2g -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 \ No newline at end of file +org.gradle.jvmargs=-Dfile.encoding=UTF-8 \ No newline at end of file diff --git a/pipelines/JenkinsFileTestCompile b/pipelines/JenkinsFileTestCompile new file mode 100644 index 0000000..aa50f0d --- /dev/null +++ b/pipelines/JenkinsFileTestCompile @@ -0,0 +1,388 @@ +def updateCommitStatus(repositoryName, status, description, accessToken, gitCommit, buildUrl, contextBuild) { + sh "./pipelines/utils/build-update.sh ${repositoryName} ${status} \"${description}\" ${accessToken} ${gitCommit} ${buildUrl} \"${contextBuild}\"" +} + +pipeline { + options { + disableConcurrentBuilds() + buildDiscarder(logRotator(numToKeepStr: '7', artifactNumToKeepStr: '7')) + } + + environment { + CONTEXT_NAME = "etendo" + BBDD_SID = "etendo" + BBDD_SID2 = "etendo2" + BBDD_PORT = "5432" + BBDD_SYSTEMUSER = "postgres" + BBDD_SYSTEMPASS = "syspass" + BBDD_USER = "tad" + BBDD_PASSWORD = "tad" + NEXUS_USER = credentials('nexus-admin-user') + NEXUS_PASSWORD = credentials('nexus-admin-passwd') + GITHUB_USER = "etendobot" + GITHUB_TOKEN = credentials('github-read-package-token') + EMAIL_ADDRESS = credentials('email_builds') + + URL_ORG_GITHUB = "https://github.com/etendosoftware" + ETENDO_BASE_URL = "https://github.com/etendosoftware/etendo_base" + PLUGIN_URL = " https://github.com/etendosoftware/com.etendoerp.gradleplugin.git" + + SUCCESS = "SUCCESS" + FAILED = "FAILED" + UNSTABLE = "UNSTABLE" + + ETENDO_DIR = "etendo_base" + REPOSITORY_NAME = "com.etendoerp.gradleplugin" + + ACCESS_TOKEN = credentials('access_token_github') + + COMMIT_INPROGRESS_STATUS = "pending" + COMMIT_SUCCESS_STATUS = "success" + COMMIT_FAILED_STATUS = "failure" + + CONTEXT_BUILD = "Testing Compilation in JAR and Source Format" + } + + agent { + kubernetes { + inheritFrom 'jenkins-node-pg' + defaultContainer 'jnlp' + yaml """ +apiVersion: v1 +kind: Pod +metadata: + name: jenkins-node-pg-0 + namespace: jenkins + labels: + app.kubernetes.io/name: jenkins-node-pg +spec: + volumes: + - name: rsa-keys + configMap: + name: rsa-keys + defaultMode: 384 + - name: docker-sock + hostPath: + path: /var/run/docker.sock + type: '' + containers: + - name: compiler + image: etendo/compiler_jenkins:1.0.6 + ports: + - name: ssh + containerPort: 22 + protocol: TCP + - name: visualvm + containerPort: 8000 + protocol: TCP + resources: + requests: + cpu: 1072m + memory: 4000Mi + limits: + cpu: 2072m + memory: 6500Mi + volumeMounts: + - name: rsa-keys + mountPath: /root/.ssh/ + - name: docker-sock + mountPath: /var/run/docker.sock + lifecycle: + postStart: + exec: + command: + - bash + - '-c' + - >- + chmod a+x /var/run/docker.sock && rm + /etc/apt/sources.list.d/pgdg.list || echo 0 && apt update && apt + install -y curl + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: IfNotPresent + - name: postgres + image: postgres:14 + workingDir: /home/jenkins + env: + - name: POSTGRES_PASSWORD + value: syspass + resources: + requests: + cpu: 1000m + memory: 1000Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: IfNotPresent + restartPolicy: Always + terminationGracePeriodSeconds: 30 + dnsPolicy: ClusterFirst + serviceAccountName: default + serviceAccount: default + securityContext: {} + """ + } + } + + stages { + stage ('Build Enviroment with Etendo Classic in JAR format') { + steps { + container('compiler') { + script { + try { + echo "---------------- Build JAR Environment ----------------" + + echo "---------------- Print Environment ----------------" + sh "printenv" + def rootDir = pwd() + def infoCommit = load "${rootDir}/pipelines/utils/infoCommits.groovy" + + def description = "Compiling Environment in JAR" + updateCommitStatus(REPOSITORY_NAME, COMMIT_INPROGRESS_STATUS, description, ACCESS_TOKEN, GIT_COMMIT, BUILD_URL, CONTEXT_BUILD) + + echo "--------------- Building Etendo JAR Environment ----------------" + sh """ + git clone ${ETENDO_BASE_URL} + cd ${ETENDO_DIR} + + echo -e "context.name=${CONTEXT_NAME} + bbdd.sid=${BBDD_SID} + bbdd.port=${BBDD_PORT} + bbdd.systemUser=${BBDD_SYSTEMUSER} + bbdd.systemPassword=${BBDD_SYSTEMPASS} + bbdd.user=${BBDD_USER} + bbdd.password=${BBDD_PASSWORD} + nexusUser=${NEXUS_USER} + nexusPassword=${NEXUS_PASSWORD} + githubUser=${GITHUB_USER} + githubToken=${GITHUB_TOKEN} + allow.root=true + org.gradle.vfs.watch=false + org.gradle.jvmargs=-Dfile.encoding=UTF-8" > gradle.properties + """ + + sh """ + cd ${ETENDO_DIR} + git clone ${PLUGIN_URL} buildSrc + cd buildSrc + git checkout ${GIT_COMMIT} + cp gradle.properties.template gradle.properties + """ + + echo "-------------------------- Commit Information Collected --------------------------" + env.PLUGIN_DIR = "${ETENDO_DIR}/buildSrc" + def commitInfoTemplate = infoCommit.generateCommitInfo(env.URL_ORG_GITHUB, null, REPOSITORY_NAME, true, env.PLUGIN_DIR) + env.COMMIT_INFO_TEMPLATE = "${commitInfoTemplate}" + echo "${env.COMMIT_INFO_TEMPLATE}" + + sh """ + sed -i "s/id 'com.etendoerp.gradleplugin'/id 'com.etendoerp.gradleplugin' \\/\\//" "${ETENDO_DIR}/build.gradle" + """ + + echo "---------------- Add dependencies ----------------" + def dependencies = env.DEPENDENCIES_FOR_BASE.split(',') + def dependenciesBlock = dependencies.collect { + "moduleDeps(\"com.etendoerp:$it:latest.release@zip\") {transitive=true}" + }.join('\n') + + dependenciesBlock += "\nimplementation(\"com.etendoerp.platform:etendo-core:latest.release\")" + + def buildGradleContent = """ + dependencies { + $dependenciesBlock + } + """ + + sh """ + cd ${ETENDO_DIR} + echo '${buildGradleContent}' >> build.gradle + cat build.gradle + """ + + echo "---------------- Build & Compile ----------------" + sh """ + cd etendo_base + echo "y" > yes + ./gradlew expandModules --info < yes + ./gradlew prepareConfig --info + ./gradlew setup --info + ./gradlew install --info + ./gradlew update.database + ./gradlew compile.complete + ./gradlew smartbuild --info + """ + + sh "rm -rf ${ETENDO_DIR}" + echo "---------------- Build JAR Environment Succesful ----------------" + currentBuild.result = SUCCESS + } catch (Exception e) { + echo "---------------- Build JAR Environment Failed ----------------" + description = "Compiling Environment in JAR Failed" + updateCommitStatus(REPOSITORY_NAME, COMMIT_FAILED_STATUS, description, ACCESS_TOKEN, GIT_COMMIT, BUILD_URL, CONTEXT_BUILD) + echo "Exception occurred: " + e.toString() + currentBuild.result = FAILED + error('Build Failed in Etendo JAR Environment') + } + } + } + } + } + stage ('Build Enviroment with Etendo Classic in Source format') { + steps { + container('compiler') { + script { + try { + description = "Compiling Environment in Source" + updateCommitStatus(REPOSITORY_NAME, COMMIT_INPROGRESS_STATUS, description, ACCESS_TOKEN, GIT_COMMIT, BUILD_URL, CONTEXT_BUILD) + echo "---------------- Build Source Environment ----------------" + + echo "---------------- Print Environment ----------------" + sh "printenv" + + echo "--------------- Building Etendo Source Environment ----------------" + sh """ + git clone ${ETENDO_BASE_URL} + cd ${ETENDO_DIR} + + echo -e "context.name=${CONTEXT_NAME} + bbdd.sid=${BBDD_SID2} + bbdd.port=${BBDD_PORT} + bbdd.systemUser=${BBDD_SYSTEMUSER} + bbdd.systemPassword=${BBDD_SYSTEMPASS} + bbdd.user=${BBDD_USER} + bbdd.password=${BBDD_PASSWORD} + nexusUser=${NEXUS_USER} + nexusPassword=${NEXUS_PASSWORD} + githubUser=${GITHUB_USER} + githubToken=${GITHUB_TOKEN} + allow.root=true + org.gradle.vfs.watch=false + org.gradle.jvmargs=-Dfile.encoding=UTF-8" > gradle.properties + """ + + sh """ + cd ${ETENDO_DIR} + git clone ${PLUGIN_URL} buildSrc + cd buildSrc + git checkout ${GIT_COMMIT} + cp gradle.properties.template gradle.properties + """ + + sh """ + sed -i "s/id 'com.etendoerp.gradleplugin'/id 'com.etendoerp.gradleplugin' \\/\\//" "${ETENDO_DIR}/build.gradle" + """ + + echo "---------------- Add dependencies ----------------" + def dependencies = env.DEPENDENCIES_FOR_BASE.split(',') + def dependenciesBlock = dependencies.collect { + "moduleDeps(\"com.etendoerp:$it:latest.release@zip\") {transitive=true}" + }.join('\n') + + def buildGradleContent = """ + dependencies { + $dependenciesBlock + } + """ + + sh """ + cd ${ETENDO_DIR} + echo '${buildGradleContent}' >> build.gradle + cat build.gradle + """ + + echo "---------------- Build & Compile ----------------" + sh """ + cd etendo_base + echo "y" > yes + ./gradlew expandCore --info < yes + ./gradlew expandModules --info < yes + ./gradlew prepareConfig --info + ./gradlew setup --info + ./gradlew install --info + ./gradlew update.database + ./gradlew compile.complete + ./gradlew smartbuild --info + """ + + echo "---------------- Build Source Environment Succesful ----------------" + currentBuild.result = SUCCESS + } catch (Exception e) { + echo "---------------- Build Source Environment Failed ----------------" + description = "Compiling Environment in Source Failed" + updateCommitStatus(REPOSITORY_NAME, COMMIT_FAILED_STATUS, description, ACCESS_TOKEN, GIT_COMMIT, BUILD_URL, CONTEXT_BUILD) + echo "Exception occurred: " + e.toString() + currentBuild.result = FAILED + error('Build Failed in Etendo Source Environment') + } + } + } + } + } + } + + post { + success { + script { + echo "---------------- DONE ----------------" + description = "Compilation Environment Successful" + updateCommitStatus(REPOSITORY_NAME, COMMIT_SUCCESS_STATUS, "Compilation Environment Successful", ACCESS_TOKEN, GIT_COMMIT, BUILD_URL, CONTEXT_BUILD) + } + } + fixed { + mail to: EMAIL_ADDRESS, + subject: "✅ FIXED - ${currentBuild.fullDisplayName}", + mimeType: "text/html", + body: """ + + + + + +

${new Date()}

+

__________________________________________________________

+ +

✅ ERRORS FIXED ✅ ✅

+ + ${env.COMMIT_INFO_TEMPLATE} + +

The problems found in the previous run/s have been fixed! 💪
Check out the output in the following link: + ${env.BUILD_URL}

+ + +

__________________________________________________________

+ + + """ + } + failure { + mail to: EMAIL_ADDRESS, + subject: "🚫 ERROR IN ${currentBuild.fullDisplayName}", + mimeType: "text/html", + body: """ + + + + + +

${new Date()}

+

__________________________________________________________

+ +

🚫 COMPILATION FAILED 🚫

+ + ${env.COMMIT_INFO_TEMPLATE} + +

The build has failed unexpectedly.
To more information on the failing run visit: ${env.BUILD_URL}

+ + +

__________________________________________________________

+ + + """ + } + } +} \ No newline at end of file diff --git a/pipelines/build-update.sh b/pipelines/build-update.sh deleted file mode 100644 index 014c4e0..0000000 --- a/pipelines/build-update.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -template='{"key": "%s", "state": "%s", "name": "%s", "url": "%s", "description": "%s"}' - -DATA=$(printf "$template" "$BUILD_ID" "$2" "$JOB_NAME" "$BUILD_URL" "$3") - -URI='https://api.bitbucket.org/2.0/repositories' -OWNER='koodu_software' -REPO_SLUG=$1 -REVISION=$GIT_COMMIT -URL="$URI/$OWNER/$REPO_SLUG/commit/$REVISION/statuses/build" - -USER=$4 -PASSWORD=$5 - -echo $URL -echo $DATA -curl -s -u "$USER:$PASSWORD" $URL --header "Content-Type: application/json" --request POST --data "$DATA" diff --git a/pipelines/utils/build-update.sh b/pipelines/utils/build-update.sh new file mode 100755 index 0000000..d819561 --- /dev/null +++ b/pipelines/utils/build-update.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +URI='api.github.com' +OWNER='etendosoftware' +REPO_SLUG=$1 +REVISION=$5 +STATUS=$2 +DESCRIPTION=$3 +TARGET_URL="$6" +ACCESS_TOKEN=$4 +CONTEXT="$7" + +GIT_STATUS_URL="https://$ACCESS_TOKEN:x-oauth-basic@$URI/repos/$OWNER/$REPO_SLUG/statuses/${REVISION}" +TEMPLATE='{"state":"%s", "target_url":"%s", "description":"%s", "context":"%s"}' +PAYLOAD=$(printf "$TEMPLATE" "$STATUS" "$TARGET_URL" "$DESCRIPTION" "$CONTEXT") + +echo "$PAYLOAD" +echo "$GIT_STATUS_URL" +curl -X POST -H "application/json" -d "$PAYLOAD" "${GIT_STATUS_URL}" \ No newline at end of file diff --git a/pipelines/utils/infoCommits.groovy b/pipelines/utils/infoCommits.groovy new file mode 100755 index 0000000..6ab2259 --- /dev/null +++ b/pipelines/utils/infoCommits.groovy @@ -0,0 +1,48 @@ +String getCommit(String directory = null) { + String changeDir = directory ? "cd ${directory} && " : '' + def command = "${changeDir}git log -1 --format=format:'%H'" + return sh(returnStdout: true, script: command).trim() +} + +String getCommitDate(String directory = null) { + String changeDir = directory ? "cd ${directory} && " : '' + def command = "${changeDir}git log -1 --date=format:'%d-%m-%Y %H:%M:%S' --pretty='%ad'" + return sh(returnStdout: true, script: command).trim() +} + +String getCommitAuthorName(String directory = null) { + String changeDir = directory ? "cd ${directory} && " : '' + def command = "${changeDir}git log -1 --pretty=format:'%an'" + return sh(returnStdout: true, script: command).trim() +} + +String getCommitAuthorEmail(String directory = null) { + String changeDir = directory ? "cd ${directory} && " : '' + def command = "${changeDir}git log -1 --pretty=format:'%ae'" + return sh(returnStdout: true, script: command).trim() +} + +String generateCommitInfo(String repoUrl, String repoGroup, String packageName, boolean includeAuthor, String directory) { + def commit = getCommit(directory) + def commitDate = getCommitDate(directory) + def formattedRepoUrl = (repoGroup == null || repoGroup.isEmpty()) ? "${repoUrl}/${packageName}" : "${repoUrl}/${repoGroup}.${packageName}" + + def urlSuffix = repoUrl.contains("bitbucket") ? "commits" : "commit" + def commitUrl = "${formattedRepoUrl}/${urlSuffix}/${commit}" + + def commitInfo = "⇢ ${packageName}:\n" + + "
    \n" + + "
  • Last Commit: ${commitUrl}
  • \n" + + if (includeAuthor) { + def commitAuthorName = getCommitAuthorName(directory) + def commitAuthorEmail = getCommitAuthorEmail(directory) + commitInfo += "
  • Author: ${commitAuthorName} (${commitAuthorEmail})
  • \n" + } + + commitInfo += "
  • Date: ${commitDate}
  • \n
" + + return commitInfo +} + +return this \ No newline at end of file From fa6c9bb3eeb0cd6362ee4b28c1a9633945f48528 Mon Sep 17 00:00:00 2001 From: etendobot Date: Tue, 12 Nov 2024 14:27:15 +0000 Subject: [PATCH 4/4] Update version to 1.5.1 :zap: --- build.gradle | 2 +- src/main/groovy/com/etendoerp/EtendoPlugin.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c90f13d..7eb1d70 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ def PROD = "prod" final String URL_PROD = "https://maven.pkg.github.com/etendosoftware/com.etendoerp.gradleplugin" final String URL_DEV = "https://repo.futit.cloud/repository/maven-public-snapshots" -final String PLUGIN_VERSION = "1.5.0" +final String PLUGIN_VERSION = "1.5.1" // Default mode def mode = DEV diff --git a/src/main/groovy/com/etendoerp/EtendoPlugin.groovy b/src/main/groovy/com/etendoerp/EtendoPlugin.groovy index 381e953..246b26b 100644 --- a/src/main/groovy/com/etendoerp/EtendoPlugin.groovy +++ b/src/main/groovy/com/etendoerp/EtendoPlugin.groovy @@ -23,7 +23,7 @@ import com.etendoerp.publication.git.CloneDependencies class EtendoPlugin implements Plugin { - final static String PLUGIN_VERSION = "1.5.0" + final static String PLUGIN_VERSION = "1.5.1" @Override void apply(Project project) {