diff --git a/build/scripts/build-allScripts.xml b/build-allScripts.xml similarity index 97% rename from build/scripts/build-allScripts.xml rename to build-allScripts.xml index 8ac79ae175..e01c17618a 100644 --- a/build/scripts/build-allScripts.xml +++ b/build-allScripts.xml @@ -3,7 +3,7 @@ - + @@ -63,7 +63,6 @@ - @@ -96,7 +95,7 @@ - mps.build.number=${mps.build.number}${line.separator}mps.date=${mps.date}${line.separator}mps.build.vcs.number=${mps.build.vcs.number}${line.separator}mps.teamcity.buildConfName=${mps.teamcity.buildConfName}${line.separator}mps.idea.platform.build.number=${mps.idea.platform.build.number}${line.separator}mps.mps.build.counter=${mps.mps.build.counter}${line.separator}mps.runtimeBuild=${mps.runtimeBuild}${line.separator}mpsBootstrapCore.version.major=${mpsBootstrapCore.version.major}${line.separator}mpsBootstrapCore.version.minor=${mpsBootstrapCore.version.minor}${line.separator}mpsBootstrapCore.version.bugfixNr=${mpsBootstrapCore.version.bugfixNr}${line.separator}mpsBootstrapCore.version.eap=${mpsBootstrapCore.version.eap}${line.separator}mpsBootstrapCore.version=${mpsBootstrapCore.version}${line.separator}com.mbeddr.platform.major.version=${com.mbeddr.platform.major.version}${line.separator}com.mbeddr.platform.minor.version=${com.mbeddr.platform.minor.version}${line.separator}com.mbeddr.platform.build=${com.mbeddr.platform.build}${line.separator}com.mbeddr.platform.mbeddr.version=${com.mbeddr.platform.mbeddr.version}${line.separator}de.itemis.mps.extensions.versionNumber=${de.itemis.mps.extensions.versionNumber}${line.separator}com.mbeddr.mpsutil.actionsfilter.major.version=${com.mbeddr.mpsutil.actionsfilter.major.version}${line.separator}com.mbeddr.mpsutil.actionsfilter.minor.version=${com.mbeddr.mpsutil.actionsfilter.minor.version}${line.separator}com.mbeddr.mpsutil.actionsfilter.build=${com.mbeddr.mpsutil.actionsfilter.build}${line.separator}com.mbeddr.mpsutil.actionsfilter.mbeddr.version=${com.mbeddr.mpsutil.actionsfilter.mbeddr.version} + mps.build.number=${mps.build.number}${line.separator}mps.date=${mps.date}${line.separator}mps.build.vcs.number=${mps.build.vcs.number}${line.separator}mps.teamcity.buildConfName=${mps.teamcity.buildConfName}${line.separator}mps.idea.platform.build.number=${mps.idea.platform.build.number}${line.separator}mps.mps.build.counter=${mps.mps.build.counter}${line.separator}mps.runtimeBuild=${mps.runtimeBuild}${line.separator}mpsBootstrapCore.version.major=${mpsBootstrapCore.version.major}${line.separator}mpsBootstrapCore.version.minor=${mpsBootstrapCore.version.minor}${line.separator}mpsBootstrapCore.version.bugfixNr=${mpsBootstrapCore.version.bugfixNr}${line.separator}mpsBootstrapCore.version.eap=${mpsBootstrapCore.version.eap}${line.separator}mpsBootstrapCore.version=${mpsBootstrapCore.version}${line.separator}com.mbeddr.platform.major.version=${com.mbeddr.platform.major.version}${line.separator}com.mbeddr.platform.minor.version=${com.mbeddr.platform.minor.version}${line.separator}com.mbeddr.platform.build=${com.mbeddr.platform.build}${line.separator}com.mbeddr.platform.mbeddr.version=${com.mbeddr.platform.mbeddr.version}${line.separator}de.itemis.mps.extensions.version=${de.itemis.mps.extensions.version}${line.separator}com.mbeddr.mpsutil.actionsfilter.major.version=${com.mbeddr.mpsutil.actionsfilter.major.version}${line.separator}com.mbeddr.mpsutil.actionsfilter.minor.version=${com.mbeddr.mpsutil.actionsfilter.minor.version}${line.separator}com.mbeddr.mpsutil.actionsfilter.build=${com.mbeddr.mpsutil.actionsfilter.build}${line.separator}com.mbeddr.mpsutil.actionsfilter.mbeddr.version=${com.mbeddr.mpsutil.actionsfilter.mbeddr.version} diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 2dd70c5f94..0000000000 --- a/build.gradle +++ /dev/null @@ -1,593 +0,0 @@ -import de.itemis.mps.gradle.* -import de.itemis.mps.gradle.tasks.MpsMigrate -import de.itemis.mps.gradle.tasks.Remigrate -import de.itemis.mps.gradle.downloadJBR.DownloadJbrForPlatform -import groovy.transform.TupleConstructor -import groovy.xml.XmlSlurper -import java.time.LocalDate -import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle - -plugins { - id 'base' - id 'maven-publish' - id 'de.itemis.mps.gradle.common' version '1.29.+' - id 'de.itemis.mps.gradle.launcher' version '2.5.2.+' - id "com.github.breadmoirai.github-release" version "2.4.1" - id "org.cyclonedx.bom" version "2.2.0" -} - -repositories { - maven { - url = 'https://artifacts.itemis.cloud/repository/maven-mps/' - } - - mavenCentral() -} - -apply plugin: 'download-jbr' - -// configure jbr download version -downloadJbr { - jbrVersion = '17.0.11-b1207.30' -} - -// detect if we are in a CI build -if (project.hasProperty("forceCI")) { - ext.ciBuild = true -} else { - //on teamcity we are in a CI build - ext.ciBuild = project.hasProperty("teamcity") -} - -def forceLocal = project.hasProperty("forceLocalDependencies") - -def major = "2024" -def minor = "1" - -// Dependency versions - - -ext.mpsVersion = '2024.1.3' - - -def mpsQAVersion = "$major.$minor+" - -// if building a against a special branch from mbeddr is required add the name here -// the name is enough no trailing "." is required, also the plain name from git can -// be used here. No need to convert "/" the script will take care of that. -def mbeddrBranch = "" -def currentBranch = "" - -if (!project.hasProperty('mbeddrVersion')) { - if (mbeddrBranch != null && !mbeddrBranch.trim().isEmpty()) { - ext.mbeddrVersion = "${mbeddrBranch.replace("/", "-")}.$major.$minor+" - } else { - ext.mbeddrVersion = "$major.$minor+" - } -} - -// Project group -group = 'org.iets3' - -// Project name cannot be defined here, see settings.gradle#rootProject.name instead -// name = 'opensource' - -// Project version -if (project.hasProperty('iets3OpenSourceVersion')) { - version = project.iets3OpenSourceVersion -} else { - if (ciBuild) { - currentBranch = GitBasedVersioning.gitBranch - - def buildNumber = System.env.BUILD_COUNTER.toInteger() - if (currentBranch.startsWith("maintenance-")) { - version = "$major.$minor.$buildNumber.${GitBasedVersioning.gitShortCommitHash}" - } else { - def isSnapshot = !(currentBranch.equals("master") || currentBranch.startsWith("datev-loon-staging-") || currentBranch.startsWith("datev-steuer-staging-")) - version = GitBasedVersioning.getVersionWithCount(major, minor, buildNumber) + (isSnapshot ? "-SNAPSHOT" : "") - } - println "##teamcity[buildNumber '${version}']" - } else { - version = "$major.$minor-SNAPSHOT" - println "Local build detected, version will be $version" - } -} - -ext.releaseRepository = 'https://artifacts.itemis.cloud/repository/maven-mps-releases/' -ext.snapshotRepository = 'https://artifacts.itemis.cloud/repository/maven-mps-snapshots' -ext.publishingRepository = version.toString().endsWith("-SNAPSHOT") ? snapshotRepository : releaseRepository - - -def buildDirPath(pathUnderBuildDir) { - project.layout.buildDirectory.dir(pathUnderBuildDir).get().asFile -} - -// 'artifacts' is used in the generated ant scripts as build output directory -ext.artifactsDir = buildDirPath('artifacts') -ext.reportsDir = buildDirPath('reports') - -wrapper { - gradleVersion = '8.13' - distributionType = Wrapper.DistributionType.ALL -} - -configurations { - mps - rerunMigrationsBackend - languageLibs - junitAnt -} - -dependencies { - mps "com.jetbrains:mps:$mpsVersion" - rerunMigrationsBackend("de.itemis.mps.build-backends:remigrate:0.2.0.+") - languageLibs "org.mpsqa:all-in-one:$mpsQAVersion" - languageLibs "com.mbeddr:platform:$mbeddrVersion" - junitAnt 'org.apache.ant:ant-junit:1.10.15' -} - -@TupleConstructor -class BundledDep { - String name - List entries - String libSolutionName - Closure configClosure = { transitive = false } - // in case a legacy dependency has a broken artifact name, e.g. w/o extension - String getConfigName() { - name + '_bundled' - } - String getResolveTaskName() { - 'resolve_' + this.configName - } -} - -def bundledDeps = [ - new BundledDep('pcollections', ['org.pcollections:pcollections:4.0.2'], 'org.iets3.core.expr.base.collections.stubs'), - new BundledDep('bigMath', ['ch.obermuhlner:big-math:2.3.2'], 'org.iets3.core.expr.math.interpreter'), - new BundledDep('functionalJava', ['org.functionaljava:functionaljava:5.0'], 'org.iets3.core.expr.genjava.functionalJava'), - new BundledDep('cpsSuite', ['io.takari.junit:takari-cpsuite:1.2.7@jar'], 'org.iets3.opensource.build.gentests.rt') -] - -bundledDeps.each { dep -> - configurations { - create(dep.configName) - } - dependencies { - dep.entries.each {entry -> - add(dep.configName, entry, dep.configClosure) - } - } - tasks.create(dep.resolveTaskName, Sync.class) { - from configurations.getByName(dep.configName) - into file("code/languages/org.iets3.opensource/solutions/${dep.libSolutionName}/lib") - - // Strip version numbers from file names - rename { filename -> - def ra = configurations.getByName(dep.configName).resolvedConfiguration.resolvedArtifacts.find { ResolvedArtifact ra -> ra.file.name == filename } - String finalName - if (ra.classifier != null) { - finalName = "${ra.name}-${ra.classifier}.${ra.extension}" - } else { - finalName = "${ra.name}.${ra.extension}" - } - return finalName - } - } -} - - -task resolveMps(type: Sync) { - dependsOn configurations.mps - from { - configurations.mps.resolve().collect { zipTree(it) } - } - into "$buildDir/mps" -} - -task resolveLanguageLibs(type: Sync) { - from { - configurations.languageLibs.resolve().collect { zipTree(it) } - } - into "$buildDir/dependencies" -} - -task resolveDependencies(dependsOn: ['downloadJbr', resolveMps, resolveLanguageLibs]) -resolveDependencies.dependsOn << bundledDeps.collect {it.resolveTaskName } - -ext.mpsHomeDir = resolveMps.destinationDir - -// Default arguments for ant scripts -def defaultScriptArgs = [ - 'mps.home' : resolveMps.destinationDir, - 'iets3.github.opensource.home' : rootDir, - 'mps.test.project.path' : "${rootDir}/code/languages/org.iets3.opensource", - 'build.jna.library.path' : new File(resolveMps.destinationDir, "lib/jna/${System.getProperty('os.arch')}"), - 'build.dir' : buildDir, - 'version' : version -] -if (gradle.startParameter.logLevel.toString() != "LIFECYCLE") { - defaultScriptArgs.put('mps.ant.log', gradle.startParameter.logLevel.toString().toLowerCase()) -} - -// enables https://github.com/mbeddr/mps-gradle-plugin#providing-global-defaults -ext["itemis.mps.gradle.ant.defaultScriptArgs"] = defaultScriptArgs.collect { "-D$it.key=$it.value".toString() } -ext["itemis.mps.gradle.ant.defaultScriptClasspath"] = project.configurations.junitAnt.getIncoming().files -afterEvaluate { - project.ext["itemis.mps.gradle.ant.defaultJavaExecutable"] = tasks.getByName('downloadJbr').javaExecutable -} - -task buildAllScripts(type: BuildLanguages, dependsOn: resolveDependencies) { - script = "$buildDir/scripts/build-allScripts.xml" -} - -task prebuild(type: BuildLanguages, dependsOn: buildAllScripts) { - script = "$buildDir/scripts/prebuild.xml" - targets "clean", "generate" -} - -task buildLanguages(type: BuildLanguages, dependsOn: prebuild) { - script = "$buildDir/scripts/build-languages.xml" -} - -task execTestsByInterpreter(type: TestLanguages, dependsOn: buildLanguages) { - script = "$buildDir/scripts/build-testInterpreter.xml" - targets "generate","build" - doLast { - ant.taskdef(name: 'junitInterpreterReport', - classname: 'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator', - classpath: configurations.junitAnt.asPath) - ant.junitInterpreterReport(toDir: "$buildDir", tofile: "AggregatedInterpreterTestSuites.xml") { - fileset(dir: "$buildDir", includes: '**/InterpreterTestSuite*.xml', excludes: 'tmp/**') - report(format: 'frames', todir: "$buildDir/junitInterpreterReport" ) - } - ant.echo("JUnit Interpreter report placed into $buildDir/junitInterpreterReport/index.html") - } -} - - -task buildAndRunTests(type: TestLanguages, dependsOn: buildLanguages) { - script = "$buildDir/scripts/build-tests.xml" - doLast { - ant.taskdef(name: 'junitreport', - classname: 'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator', - classpath: configurations.junitAnt.asPath) - ant.junitreport { - fileset(dir: "$buildDir", includes: '**/TEST*.xml', excludes: 'tmp/**') - report(format: 'frames', todir: "$buildDir/junitreport") - } - ant.echo("JUnit report placed into $buildDir/junitreport/index.html") - } -} - -task failOnTestError() { - description = 'evaluate junit result and fail on error' - doLast { - - def juniXml = file('TESTS-TestSuites.xml') - if(juniXml.exists()){ - def junitResult = new XmlSlurper().parse(juniXml) - def failures = junitResult.'**'.findAll { it.name() == 'failure' } - def errors = junitResult.'**'.findAll { it.name() == 'error' } - - if (failures || errors) { - def amount = failures.size() + errors.size() - throw new GradleException(amount + " JUnit tests failed. Check the test report for details.") - } - } - } -} -buildAndRunTests.configure { finalizedBy failOnTestError } -check.dependsOn buildAndRunTests - -tasks.register('migrate', MpsMigrate) { - dependsOn(resolveMps, 'resolveMpsForModelcheck', 'downloadJbr', 'buildLanguages', 'buildAndRunTests') - javaLauncher = tasks.named('downloadJbr', DownloadJbrForPlatform).flatMap { it.javaLauncher } - - haltOnPrecheckFailure = false - haltOnDependencyError = true - - mpsHome = mpsHomeDir - - projectDirectories.from('code/languages/org.iets3.opensource') - folderMacros['iets3.github.opensource.home'] = rootProject.layout.projectDirectory - - pluginRoots.from(new File(mpsHomeDir, 'plugins')) - - maxHeapSize = '4G' -} - -tasks.register('remigrate', Remigrate) { - mustRunAfter('migrate') - mustRunAfter('buildLanguages', 'buildAndRunTests') - - dependsOn(resolveMps, 'resolveMpsForModelcheck','downloadJbr') - - javaLauncher = tasks.named('downloadJbr', DownloadJbrForPlatform).flatMap { it.javaLauncher } - - mpsHome = mpsHomeDir - projectDirectories.from('code/languages/org.iets3.opensource') - folderMacros['iets3.github.opensource.home'] = rootProject.layout.projectDirectory - - pluginRoots.from(new File(mpsHomeDir, 'plugins')) - maxHeapSize = '4G' -} - -apply plugin: 'modelcheck' - -File modelcheckresult = new File("$buildDir/TEST-checkProject.xml") - -def pluginsList = [] - -modelcheck { - projectLocation = new File("$projectDir/code/languages/org.iets3.opensource") - mpsLocation = new File("$buildDir/mps") - plugins = pluginsList - mpsConfig = configurations.mps - macros = [new Macro("iets3.github.opensource.home", "$projectDir")] - junitFile = modelcheckresult - junitFormat = "message" - errorNoFail = true - debug = false - maxHeap = "4G" -} - - -afterEvaluate { project -> - /* - check.configure { - dependsOn tasks.named('checkmodels') - } - */ -} - - -checkmodels { - dependsOn(resolveMps) -} - -task packageLanguages(type: Zip, dependsOn: [buildLanguages, cyclonedxBom]) { - archiveBaseName = 'org.iets3.opensource' - from(artifactsDir) { - include 'org.iets3.opensource/**' - } - from(reportsDir) { - include 'sbom.json' - into 'org.iets3.opensource' - } -} - -task packageTests(type: Zip, dependsOn: buildAndRunTests) { - archiveBaseName = 'org.iets3.opensource.tests' - from artifactsDir - include 'org.iets3.opensource.tests/**' -} - -task buildDistroWithDependencies(type: RunAntScript, dependsOn: buildLanguages) { - script = "$buildDir/scripts/build-distro.xml" - targets 'clean', 'assemble' -} - -task packageDistroWithDependencies(type: Zip, dependsOn: buildDistroWithDependencies) { - archiveBaseName = 'org.iets3.opensource-with-dependencies' - from artifactsDir - include 'org.iets3.opensource.distro/**' -} - -assemble.dependsOn packageLanguages, packageTests - -static def addDependency(Object pom, Object groupId, Object artifactId, Object version, Object type = null, String scope = null) { - pom.withXml { XmlProvider prov -> - Node root = prov.asNode() - Node deps = root.dependencies[0] ?: root.appendNode("dependencies") - def dep = deps.appendNode("dependency") - dep.appendNode("groupId", groupId) - dep.appendNode("artifactId", artifactId) - dep.appendNode("version", version) - if (type != null) { - dep.appendNode("type", type) - } - if (scope != null) { - dep.appendNode("scope", scope) - } - } -} - -static def addDependency(MavenPom pom, Configuration config, String scope = null) { - config.resolvedConfiguration.firstLevelModuleDependencies.each { - addDependency(pom, it.moduleGroup, it.moduleName, it.moduleVersion, it.moduleArtifacts[0].type, scope) - } -} - -ext.additionalPomInfo = { - licenses { - // official SPDX identifier - // see https://spdx.org/licenses/ for list - license { - name = "Apache-2.0" - url = "https://www.apache.org/licenses/LICENSE-2.0" - comments = "Apache License Version 2.0" - distribution = "repo" - } - } - organization { - name = "itemis AG" - url = "https://www.itemis.com" - } - scm { - tag = GitBasedVersioning.getGitCommitHash() - url = "https://github.com/IETS3/iets3.opensource" - } -} - -ext.addBundledDependencies = { MavenPom pom -> - bundledDeps.each { - addDependency(pom, configurations[it.configName], 'provided') - } -} - -publishing { - repositories { - maven { - url = project.publishingRepository - if (project.hasProperty("artifacts.itemis.cloud.user") && project.hasProperty("artifacts.itemis.cloud.pw")) { - credentials { - username = project.findProperty("artifacts.itemis.cloud.user") - password = project.findProperty("artifacts.itemis.cloud.pw") - } - } - } - if (currentBranch == "master" || currentBranch.startsWith("maintenance") ) { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/IETS3/iets3.opensource") - if (project.hasProperty("gpr.token")) { - credentials { - username = project.findProperty("gpr.user") - password = project.findProperty("gpr.token") - } - } - } - } - } - - publications { - opensource(MavenPublication) { - groupId = group - artifactId = name - artifact packageLanguages - - addDependency(pom, configurations.languageLibs) - - pom addBundledDependencies - - pom additionalPomInfo - } - - tests(MavenPublication) { - groupId = 'org.iets3.opensource' - artifactId = 'tests' - artifact packageTests - addDependency(pom, 'org.iets3', 'opensource', project.version, 'zip') - - pom additionalPomInfo - } - - def runtimesDir = new File(artifactsDir, 'org.iets3.opensource/org.iets3.core.os/languages/iets3.core.os') - - 'org.iets3.core.expr.base.shared.runtime'(MavenPublication) { - groupId = 'org.iets3.core.expr.base.shared' - artifactId = 'shared-runtime' - artifact(new File(runtimesDir, 'org.iets3.core.expr.base.shared.runtime.jar')) { - builtBy buildLanguages - } - artifact(new File(runtimesDir, 'org.iets3.core.expr.base.shared.runtime-src.jar')) { - builtBy buildLanguages - classifier = 'sources' - } - - pom additionalPomInfo - } - - 'org.iets3.core.expr.simpleTypes.runtime'(MavenPublication) { - // GitHub Packages refuse uppercase artifactId (not sure about groupId) so use lower case here - groupId = 'org.iets3.core.expr.simpletypes' - artifactId = 'simpletypes-runtime' - artifact(new File(runtimesDir, 'org.iets3.core.expr.simpleTypes.runtime.jar')) { - builtBy buildLanguages - } - artifact(new File(runtimesDir, 'org.iets3.core.expr.simpleTypes.runtime-src.jar')) { - builtBy buildLanguages - classifier = 'sources' - } - - addDependency(pom, 'org.iets3.core.expr.base.shared', 'shared-runtime', project.version) - - pom additionalPomInfo - } - - 'org.iets3.core.expr.datetime.runtime'(MavenPublication) { - groupId = 'org.iets3.core.expr.datetime' - artifactId = 'datetime-runtime' - artifact(new File(runtimesDir, 'org.iets3.core.expr.datetime.runtime.jar')) { - builtBy buildLanguages - } - artifact(new File(runtimesDir, 'org.iets3.core.expr.datetime.runtime-src.jar')) { - builtBy buildLanguages - classifier = 'sources' - } - - addDependency(pom, 'org.iets3.core.expr.base.shared', 'shared-runtime', project.version) - - pom additionalPomInfo - } - - 'org.iets3.core.expr.temporal.runtime'(MavenPublication) { - groupId = 'org.iets3.core.expr.temporal' - artifactId = 'temporal-runtime' - artifact(new File(runtimesDir, 'org.iets3.core.expr.temporal.runtime.jar')) { - builtBy buildLanguages - } - artifact(new File(runtimesDir, 'org.iets3.core.expr.temporal.runtime-src.jar')) { - builtBy buildLanguages - classifier = 'sources' - } - - addDependency(pom, 'org.iets3.core.expr.datetime', 'datetime-runtime', project.version) - - pom additionalPomInfo - } - } -} - -defaultTasks 'buildLanguages' - -/* def listMergedPRs = { - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'sh', './listMergedPRs.sh' - standardOutput = stdout - } - stdout.toString() -} */ - -def currentDate = LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)) -// def prCommitsList = "${-> listMergedPRs().readLines().collect { line -> "- $line"}.join("\n")}" -def langLibDeps = project.configurations.languageLibs.resolvedConfiguration.lenientConfiguration.allModuleDependencies -def depsList = langLibDeps.collect {"- `${it.moduleGroup}:${it.moduleName}` : `${it.moduleVersion}`"}.join("\n") -def releaseNotes = """Automated Nighly build from ${currentDate}. - -Includes dependencies: -${depsList} -""" - -githubRelease { - owner = 'IETS3' - repo = 'iets3.opensource' - token = rootProject.findProperty('github.token') ?: 'empty' - tagName = 'nightly-' + version - targetCommitish = GitBasedVersioning.getGitCommitHash() - body = releaseNotes - prerelease = true - releaseAssets = packageDistroWithDependencies.outputs.files.collect {it.path} - dryRun = false -} - -tasks.named('githubRelease').configure { - dependsOn packageDistroWithDependencies -} - -cyclonedxBom { - // SBOM destination directory - destination = reportsDir - // The file name for the generated SBOMs (before the file format suffix) - outputName = "sbom" - // The file format generated, can be xml, json or all for generating both - outputFormat = "json" - // Don't include license texts in generated SBOMs - includeLicenseText = false - // Include runtime only deps (bundled libs, language libs, mps) - def runtimeConfigs = bundledDeps.collect {it.configName } - runtimeConfigs.addAll([configurations.mps.name, configurations.languageLibs.name]) - includeConfigs = runtimeConfigs -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000000..267d8c7a7a --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,527 @@ +import de.itemis.mps.gradle.BuildLanguages +import de.itemis.mps.gradle.GitBasedVersioning +import de.itemis.mps.gradle.Macro +import de.itemis.mps.gradle.RunAntScript +import de.itemis.mps.gradle.TestLanguages +import de.itemis.mps.gradle.tasks.MpsMigrate +import de.itemis.mps.gradle.tasks.Remigrate +import groovy.util.Node +import groovy.util.NodeList +import groovy.xml.XmlSlurper +import java.time.LocalDate +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle +import java.util.Locale + +plugins { + base + `maven-publish` + alias(libs.plugins.mpsCommon) + alias(libs.plugins.mpsLauncher) + alias(libs.plugins.githubRelease) + alias(libs.plugins.cyclonedxBom) + alias(libs.plugins.downloadJbr) + alias(libs.plugins.modelcheck) +} + +repositories { + maven("https://artifacts.itemis.cloud/repository/maven-mps/") + mavenCentral() +} + +val mps: Configuration by configurations.creating +val rerunMigrationsBackend: Configuration by configurations.creating +val languageLibs: Configuration by configurations.creating +val junitAnt: Configuration by configurations.creating +val pcollections: Configuration by configurations.creating +val bigMath: Configuration by configurations.creating +val functionalJava: Configuration by configurations.creating +val cpSuite: Configuration by configurations.creating + +dependencies { + mps(libs.mps) + rerunMigrationsBackend(libs.remigrate) + languageLibs(libs.mpsQaAllInOne) + languageLibs(libs.mbeddrPlatform) + junitAnt(libs.antJunit) + + // Bundled dependencies + pcollections(libs.pcollections) { isTransitive = false } + bigMath(libs.bigMath) { isTransitive = false } + functionalJava(libs.functionalJava) { isTransitive = false } + // we need to explicitly state the jar type for this dependency + cpSuite(libs.cpSuite.get().toString() + "@jar") { isTransitive = false } +} + +tasks.wrapper { + gradleVersion = libs.versions.gradle.get() + distributionType = Wrapper.DistributionType.ALL +} + +downloadJbr { + jbrVersion = libs.versions.jbr.get() +} + +val ciBuild by extra(project.hasProperty("forceCI") || project.hasProperty("teamcity")) +val branch: String = GitBasedVersioning.getGitBranch() + +group = "org.iets3" + +version = calculateVersion().also { + if (ciBuild) logger.lifecycle( "##teamcity[buildNumber '$it']") + else logger.lifecycle( "Local build detected, version will be '$it'") +} + +fun calculateVersion(): String { + val major = libs.versions.mpsVersion.get().substring(0, 4) + val minor = libs.versions.mpsVersion.get().substring(5, 6) + if (!ciBuild) return "$major.$minor-SNAPSHOT" + + val buildNumber = + checkNotNull(System.getenv("BUILD_COUNTER")?.toIntOrNull()) { "env BUILD_COUNTER not found or not a valid int" } + if (branch.startsWith("maintenance-")) + return "$major.$minor.$buildNumber.${GitBasedVersioning.getGitShortCommitHash()}" + + val isSnapshot = + !(branch == "master" || branch.startsWith("datev-loon-staging-") || branch.startsWith("datev-steuer-staging-")) + val baseVersion = GitBasedVersioning.getVersionWithCount(major, minor, buildNumber) + return if (isSnapshot) "$baseVersion-SNAPSHOT" else baseVersion +} + +val mpsHomeDir by extra(layout.buildDirectory.dir("mps").get()) +val artifactsDir by extra(project.layout.buildDirectory.dir("artifacts").get()) +val reportsDir by extra(project.layout.buildDirectory.dir("reports").get()) +val scriptsDir by extra(project.layout.buildDirectory.dir("scripts").get()) + +val bundledDepsToLibSolution = mapOf( + pcollections to "org.iets3.core.expr.base.collections.stubs", + bigMath to "org.iets3.core.expr.math.interpreter", + functionalJava to "org.iets3.core.expr.genjava.functionalJava", + cpSuite to "org.iets3.opensource.build.gentests.rt" +) + +val bundledDependencies = bundledDepsToLibSolution.keys.toList() +val bundledDependencyResolveTasks = bundledDepsToLibSolution.map { (conf, libSolutionName) -> + conf.registerTaskToResolveBundledDependency(libSolutionName) +} + +fun Configuration.registerTaskToResolveBundledDependency( + libSolutionName: String +): TaskProvider { + val configName = this@registerTaskToResolveBundledDependency.name + return tasks.register("resolve_${configName}_bundled") { + from(this@registerTaskToResolveBundledDependency) + into(file("code/languages/org.iets3.opensource/solutions/$libSolutionName/lib")) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + // Strip version numbers from file names + rename { filename -> + val resolvedArtifact = checkNotNull( + configurations.getByName(configName).resolvedConfiguration.resolvedArtifacts + .find { resolvedArtifact: ResolvedArtifact -> resolvedArtifact.file.name == filename }) + + return@rename if (resolvedArtifact.classifier != null) { + "${resolvedArtifact.name}-${resolvedArtifact.classifier}.${resolvedArtifact.extension}" + } else { + "${resolvedArtifact.name}.${resolvedArtifact.extension}" + } + } + } +} + +val resolveMPS by tasks.registering(Sync::class) { + dependsOn(mps) + from(mps.resolve().map { zipTree(it) }) + into(mpsHomeDir) +} + +val resolveLanguageLibs by tasks.registering(Sync::class) { + from(languageLibs.resolve().map { zipTree(it) }) + into(layout.buildDirectory.dir("dependencies")) +} + +val resolveDependencies by tasks.registering { + dependsOn(tasks.downloadJbr, resolveMPS, resolveLanguageLibs) + bundledDependencyResolveTasks.forEach { dependsOn(it) } +} + +// Default arguments for ant scripts +val defaultScriptArgs = mutableMapOf( + "mps.home" to mpsHomeDir.asFile, + "mps.test.project.path" to "${rootDir}/code/languages/org.iets3.opensource", + "iets3.github.opensource.home" to rootDir, + "build.jna.library.path" to mpsHomeDir.file("lib/jna/${System.getProperty("os.arch")}").asFile, + "build.dir" to layout.buildDirectory.get().asFile, + "version" to version, +) + +if (gradle.startParameter.logLevel != LogLevel.LIFECYCLE) { + defaultScriptArgs["mps.ant.log"] = gradle.startParameter.logLevel.toString().lowercase(Locale.getDefault()) +} + +// enables https://github.com/mbeddr/mps-gradle-plugin#providing-global-defaults +extra["itemis.mps.gradle.ant.defaultScriptArgs"] = defaultScriptArgs.map { "-D${it.key}=${it.value}" } +extra["itemis.mps.gradle.ant.defaultScriptClasspath"] = junitAnt.incoming.files + +afterEvaluate { + extra["itemis.mps.gradle.ant.defaultJavaExecutable"] = tasks.downloadJbr.get().javaExecutable +} + +val buildAllScripts by tasks.registering(BuildLanguages::class) { + dependsOn(resolveDependencies) + script = rootDir.resolve("build-allScripts.xml") +} + +val prebuild by tasks.registering(BuildLanguages::class) { + dependsOn(buildAllScripts) + script = scriptsDir.file("prebuild.xml") + targets("clean", "generate") +} + +val buildLanguages by tasks.registering(BuildLanguages::class) { + dependsOn(prebuild) + script = scriptsDir.file("build-languages.xml") +} + +val execTestsByInterpreter by tasks.registering(TestLanguages::class) { + script = scriptsDir.file("build-testInterpreter.xml") + targets("generate", "build") + doLast { + // there is limited ant support for kotlin so we fall back to groovy + ant.withGroovyBuilder { + "taskdef"( + "name" to "junitInterpreterReport", + "classname" to "org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator", + "classpath" to junitAnt.asPath + ) + "junitInterpreterReport"("toDir" to "${layout.buildDirectory.get()}") { + "fileset"( + "dir" to "${layout.buildDirectory.get()}", + "includes" to "**/InterpreterTestSuite*.xml", + "excludes" to "tmp/**" + ) + "report"("format" to "frames", "todir" to "${layout.buildDirectory.get()}/junitInterpreterReport") + } + "echo"("JUnit Interpreter report placed into ${layout.buildDirectory.get()}/junitInterpreterReport/index.html") + } + } +} + +val buildAndRunTests by tasks.registering(TestLanguages::class) { + dependsOn(buildAllScripts) + script = scriptsDir.file("build-tests.xml") + finalizedBy(failOnTestError) + doLast { + // there is limited ant support for kotlin so we fall back to groovy + ant.withGroovyBuilder { + "taskdef"( + "name" to "junitreport", + "classname" to "org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator", + "classpath" to junitAnt.asPath + ) + "junitreport" { + "fileset"( + "dir" to "${layout.buildDirectory.get()}", + "includes" to "**/TEST*.xml", + "excludes" to "tmp/**" + ) + "report"( + "format" to "frames", + "todir" to "${layout.buildDirectory.get()}/junitreport" + ) + } + "echo"("JUnit report placed into ${layout.buildDirectory.get()}/junitreport/index.html") + } + } +} + +val failOnTestError by tasks.registering { + description = "evaluate junit result and fail on error" + doLast { + val junitXml = file("TESTS-TestSuites.xml") + if (junitXml.exists()) { + val junitResult = XmlSlurper().parse(junitXml) + val testSuites = junitResult.childNodes().asSequence().map { it as groovy.xml.slurpersupport.Node } + val errorsAndFailures = testSuites.sumOf { + it.attributes()["errors"].toString().toInt() + it.attributes()["failures"].toString().toInt() + } + if (errorsAndFailures > 0) { + throw GradleException("$errorsAndFailures JUnit tests failed. Check the report for details.") + } + } + } +} + +tasks.check { + dependsOn(buildAndRunTests) +} + +tasks.assemble { + dependsOn(buildLanguages) +} + +val migrate by tasks.registering(MpsMigrate::class) { + dependsOn(resolveMPS, "resolveMpsForModelcheck", tasks.downloadJbr, buildLanguages, buildAndRunTests) + javaLauncher.set(tasks.downloadJbr.get().javaLauncher) + haltOnPrecheckFailure.set(false) + haltOnDependencyError.set(false) + mpsHome.set(mpsHomeDir) + projectDirectories.from("code/languages/org.iets3.opensource") + folderMacros.put("iets3.github.opensource.home", rootProject.layout.projectDirectory) + pluginRoots.from(mpsHomeDir.dir("plugins")) + maxHeapSize.set("4G") +} + +val remigrate by tasks.registering(Remigrate::class) { + mustRunAfter(migrate, buildLanguages, buildAndRunTests) + dependsOn(resolveMPS, "resolveMpsForModelcheck", tasks.downloadJbr) + javaLauncher.set(tasks.downloadJbr.get().javaLauncher) + mpsHome.set(mpsHomeDir) + projectDirectories.from("code/languages/org.iets3.opensource") + folderMacros.put("iets3.github.opensource.home", rootProject.layout.projectDirectory) + pluginRoots.from(mpsHomeDir.dir("plugins")) + maxHeapSize = "4G" +} + +modelcheck { + projectLocation = File("$projectDir/code/languages/org.iets3.opensource") + mpsLocation = mpsHomeDir.asFile + pluginsProperty.set(emptyList()) + mpsConfig = mps + macros = listOf(Macro("iets3.github.opensource.home", "$projectDir")) + junitFile = layout.buildDirectory.file("TEST-checkProject.xml").get().asFile + junitFormat = "message" + errorNoFail = true + debug = false + maxHeap = "4G" +} + +tasks.checkmodels { dependsOn(resolveMPS) } + +val packageLanguages by tasks.registering(Zip::class) { + dependsOn(buildLanguages, tasks.cyclonedxBom) + from(artifactsDir) { + include("org.iets3.opensource/**") + } + from(reportsDir) { + include("sbom.json") + into("org.iets3.opensource") + } +} + +val packageTests by tasks.registering(Zip::class) { + dependsOn(buildAndRunTests) + archiveBaseName.set("org.iets3.opensource.tests") + from(artifactsDir) + include("org.iets3.opensource.tests/**") +} + +val buildDistroWithDependencies by tasks.registering(RunAntScript::class) { + dependsOn(buildLanguages) + script = scriptsDir.file("build-distro.xml") + targets("clean", "assemble") +} + +val packageDistroWithDependencies by tasks.registering(Zip::class) { + archiveBaseName.set("org.iets3.opensource-with-dependencies") + from(artifactsDir) + include("org.iets3.opensource.distro/**") +} + +fun MavenPom.addDependency(configuration: Configuration, scope: String? = null) { + configuration.resolvedConfiguration.firstLevelModuleDependencies.forEach { + addDependency(it.moduleGroup, it.moduleName, it.moduleVersion, it.moduleArtifacts.first().type, scope) + } +} + +fun MavenPom.addDependency(moduleGroup: String, moduleName: String, moduleVersion: String, type: String? = null, scope: String? = null) { + withXml { + val root = asNode() + val dependencies = + (root.get("dependencies") as? NodeList)?.getOrNull(0) as Node? ?: root.appendNode("dependencies") + dependencies.appendNode("dependency").apply { + appendNode("groupId", moduleGroup) + appendNode("artifactId", moduleName) + appendNode("version", moduleVersion) + type?.let { appendNode("type", it) } + scope?.let { appendNode("scope", it) } + } + } +} + +fun MavenPom.includeAdditionalInfo() { + licenses { + // official SPDX identifier + // see https://spdx.org/licenses/ for list + license { + name.set("Apache-2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0") + comments.set("Apache License Version 2.0") + distribution.set("repo") + } + } + organization { + name.set("itemis AG") + url.set("https://www.itemis.com") + } + scm { + tag.set(GitBasedVersioning.getGitCommitHash()) + url.set("https://github.com/IETS3/iets3.opensource") + } +} + +fun MavenPom.addBundledDependencies() = bundledDependencies.forEach { addDependency(it, "provided") } + +publishing { + repositories { + maven { + val publishingRepository = if (version.toString().endsWith("-SNAPSHOT")) + "https://artifacts.itemis.cloud/repository/maven-mps-snapshots" + else + "https://artifacts.itemis.cloud/repository/maven-mps-releases/" + url = uri(publishingRepository) + if (project.hasProperty("artifacts.itemis.cloud.user") && project.hasProperty("artifacts.itemis.cloud.pw")) { + credentials { + username = project.findProperty("artifacts.itemis.cloud.user").toString() + password = project.findProperty("artifacts.itemis.cloud.pw").toString() + } + } + } + if (branch == "master" || branch.startsWith("maintenance")) { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/IETS3/iets3.opensource") + if (project.hasProperty("gpr.token")) { + credentials { + username = project.findProperty("gpr.user").toString() + password = project.findProperty("gpr.token").toString() + } + } + } + } + } + publications { + create("opensource") { + groupId = group.toString() + artifactId = project.name + artifact(packageLanguages) + + pom.addDependency(languageLibs) + pom.includeAdditionalInfo() + } + + create("tests") { + groupId = "org.iets3.opensource" + artifactId = "tests" + artifact(packageTests) + + pom.addDependency( + moduleGroup = "org.iets3", + moduleName = "opensource", + moduleVersion = project.version.toString(), + type = "zip" + ) + pom.addBundledDependencies() + pom.includeAdditionalInfo() + } + val runtimesDir = file(artifactsDir).resolve("org.iets3.opensource/org.iets3.core.os/languages/iets3.core.os") + + create("org.iets3.core.expr.base.shared.runtime") { + groupId = "org.iets3.core.expr.base.shared" + artifactId = "shared-runtime" + artifact(file(runtimesDir.resolve("org.iets3.core.expr.base.shared.runtime.jar"))) { + builtBy(buildLanguages) + } + artifact(file(runtimesDir.resolve("org.iets3.core.expr.base.shared.runtime-src.jar"))) { + builtBy(buildLanguages) + classifier = "sources" + } + pom.includeAdditionalInfo() + } + + create("org.iets3.core.expr.simpleTypes.runtime") { + groupId = "org.iets3.core.expr.simpletypes" + artifactId = "simpletypes-runtime" + artifact(file(runtimesDir.resolve("org.iets3.core.expr.simpleTypes.runtime.jar"))) { + builtBy(buildLanguages) + } + artifact(file(runtimesDir.resolve("org.iets3.core.expr.simpleTypes.runtime-src.jar"))) { + builtBy(buildLanguages) + classifier = "sources" + } + pom.addDependency("org.iets3.core.expr.base.shared", "shared-runtime", project.version.toString()) + pom.includeAdditionalInfo() + } + + create("org.iets3.core.expr.datetime.runtime") { + groupId = "org.iets3.core.expr.datetime" + artifactId = "datetime-runtime" + artifact(file(runtimesDir.resolve("org.iets3.core.expr.datetime.runtime.jar"))) { + builtBy(buildLanguages) + } + artifact(file(runtimesDir.resolve("org.iets3.core.expr.datetime.runtime-src.jar"))) { + builtBy(buildLanguages) + classifier = "sources" + } + + pom.addDependency("org.iets3.core.expr.base.shared", "shared-runtime", project.version.toString()) + pom.includeAdditionalInfo() + } + + create("org.iets3.core.expr.temporal.runtime") { + groupId = "org.iets3.core.expr.temporal" + artifactId = "temporal-runtime" + artifact(file(runtimesDir.resolve("org.iets3.core.expr.temporal.runtime.jar"))) { + builtBy(buildLanguages) + } + artifact(file(runtimesDir.resolve("org.iets3.core.expr.temporal.runtime-src.jar"))) { + builtBy(buildLanguages) + classifier = "sources" + } + + pom.addDependency("org.iets3.core.expr.datetime", "datetime-runtime", project.version.toString()) + pom.includeAdditionalInfo() + } + } +} + +defaultTasks.add(tasks.assemble.name) + +githubRelease { + owner("IETS3") + repo("iets3.opensource") + token(rootProject.findProperty("github.token").toString()) + tagName("nightly-$version") + targetCommitish(GitBasedVersioning.getGitCommitHash()) + val currentDate = LocalDate.now().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)) + val dependencyList = + languageLibs.resolvedConfiguration.lenientConfiguration.allModuleDependencies.joinToString("\n") { + "- `${it.moduleGroup}:${it.moduleName}` : `${it.moduleVersion}`" + } + body { + """ + Automated Nightly build from ${currentDate}. + // + //Includes dependencies: + //${dependencyList} + """.trimIndent() + } + prerelease(true) + releaseAssets(packageDistroWithDependencies.get().outputs.files.map { it.path }) + dryRun(false) +} +tasks.githubRelease { + dependsOn(packageDistroWithDependencies) +} + +tasks.cyclonedxBom { + // SBOM destination directory + destination.set(reportsDir.asFile) + // The file name for the generated SBOMs (before the file format suffix) + outputName.set("sbom") + // The file format generated, can be xml, json or all for generating both + outputFormat.set("json") + // Don't include license texts in generated SBOMs + includeLicenseText.set(false) + // Included bundled runtime dependencies + includeConfigs.set(bundledDependencies.map { it.name }) +} diff --git a/code/languages/org.iets3.opensource/solutions/org.iets3.opensource.allScripts.build/models/org/iets3/opensource/allScripts/build/build.mps b/code/languages/org.iets3.opensource/solutions/org.iets3.opensource.allScripts.build/models/org/iets3/opensource/allScripts/build/build.mps index 5d5bfea610..4201b2af74 100644 --- a/code/languages/org.iets3.opensource/solutions/org.iets3.opensource.allScripts.build/models/org/iets3/opensource/allScripts/build/build.mps +++ b/code/languages/org.iets3.opensource/solutions/org.iets3.opensource.allScripts.build/models/org/iets3/opensource/allScripts/build/build.mps @@ -139,7 +139,7 @@ - + @@ -490,14 +490,7 @@ - - - - - - - - + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000000..989a9963fd --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,33 @@ +[versions] +mpsVersion = "2024.1.3" +mpsQaVersion = "2024.1.+" +# if you want to build against a specific mbeddr branch, prepend it here with a dot. +# NOTE: instances of '/' in the branch name need to be replaced by '-' +# example: mbeddrVersion="feature-my_new_feature.2023.2.+" +mbeddrVersion = "2024.1.+" + +gradle = "8.13" +jbr = "17.0.11-b1207.30" + +[libraries] +mps = { group = "com.jetbrains", name = "mps", version.ref = "mpsVersion" } +remigrate = { group = "de.itemis.mps.build-backends", name = "remigrate", version = "0.2.0" } +mpsQaAllInOne = { group = "org.mpsqa", name = "all-in-one", version.ref = "mpsQaVersion" } +mbeddrPlatform = { group = "com.mbeddr", name = "platform", version.ref = "mbeddrVersion" } +antJunit = { group = "org.apache.ant", name = "ant-junit", version = "1.10.15" } + +# bundled dependencies +pcollections = { group = "org.pcollections", name = "pcollections", version = "4.0.2" } +bigMath = { group = "ch.obermuhlner", name = "big-math", version = "2.3.2" } +functionalJava = { group = "org.functionaljava", name = "functionaljava", version = "5.0" } +cpSuite = { group = "io.takari.junit", name = "takari-cpsuite", version = "1.2.7" } + +[bundles] + +[plugins] +cyclonedxBom = { id = "org.cyclonedx.bom", version = "2.2.0" } +downloadJbr = { id = "download-jbr", version = "1.29.3.+" } +githubRelease = { id = "com.github.breadmoirai.github-release", version = "2.4.1" } +modelcheck = { id = "modelcheck", version = "1.29.3.+" } +mpsCommon = { id = "de.itemis.mps.gradle.common", version = "1.29.+" } +mpsLauncher = { id = "de.itemis.mps.gradle.launcher", version = "2.5.2.+" } diff --git a/settings.gradle b/settings.gradle.kts similarity index 62% rename from settings.gradle rename to settings.gradle.kts index 88ce74266d..ad2dc4eee6 100644 --- a/settings.gradle +++ b/settings.gradle.kts @@ -1,11 +1,10 @@ pluginManagement { repositories { - maven { url = 'https://artifacts.itemis.cloud/repository/maven-mps' } + maven("https://artifacts.itemis.cloud/repository/maven-mps") // Need to manually include the default Gradle plugin portal repository when overriding the defaults. gradlePluginPortal() } } -rootProject.name = 'opensource' - +rootProject.name = "opensource"