From b451f8121169ce1978473ad770fc106a59c3bf2f Mon Sep 17 00:00:00 2001 From: Nick Garay Date: Mon, 25 May 2026 13:56:25 -0400 Subject: [PATCH 1/5] Fix repo information for publication --- build.gradle | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 67bd45d..af970cb 100644 --- a/build.gradle +++ b/build.gradle @@ -350,38 +350,37 @@ subprojects { artifact(p.tasks.osgi) { classifier = 'bundle' } - + pom.withXml { asNode().get('version') + ({ resolveStrategy = Closure.DELEGATE_FIRST name p.description if (p.details != null) description p.details - url 'http://www.opensensorhub.org' + url 'https://georobotix.us' licenses { license { - name 'Mozilla Public License Version 2.0' - url 'http://www.mozilla.org/MPL/2.0' + name 'Proprietary – All rights reserved' + url 'https://georobotix.us//legal' distribution 'repo' } } scm { - url 'https://github.com/opensensorhub/osh-addons' - connection 'scm:git:git://github.com/opensensorhub/osh-addons.git' + url 'https://github.com/Botts-Innovative-Research/no-code-addons' + connection 'scm:git:git://github.com/Botts-Innovative-Research/socom-addons.git' } issueManagement { - url 'https://github.com/opensensorhub/osh-addons/issues' + url 'https://github.com/Botts-Innovative-Research/no-code-addons/issues' system 'GitHub Issues' } } >> p.pom) - } - } + } } } repositories { //mavenLocal() maven { name = "GitHubPackages" - url = "https://maven.pkg.github.com/opensensorhub/osh-addons" + url = "https://maven.pkg.github.com/Botts-Innovative-Research/no-code-addons" credentials { username = System.getenv("GITHUB_ACTOR") password = System.getenv("GITHUB_TOKEN") From 26609f1ce09cf38b81cd4edbe9d8914732e08e04 Mon Sep 17 00:00:00 2001 From: Nick Garay Date: Mon, 25 May 2026 14:03:20 -0400 Subject: [PATCH 2/5] Fix repo scm information for publication --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index af970cb..7d1321f 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ allprojects { apply from: 'readmes.gradle' -ext.oshCoreVersion = '2.0-beta2' +ext.oshCoreVersion = '2.0.0-beta.3' description = 'No-Code Add-ons' tasks.register("harvestBundles", Copy) { @@ -367,7 +367,7 @@ subprojects { } scm { url 'https://github.com/Botts-Innovative-Research/no-code-addons' - connection 'scm:git:git://github.com/Botts-Innovative-Research/socom-addons.git' + connection 'scm:git:git://github.com/Botts-Innovative-Research/no-code.git' } issueManagement { url 'https://github.com/Botts-Innovative-Research/no-code-addons/issues' From 625b9e97ed30c506ad2a5955f9680b6dd7238ee7 Mon Sep 17 00:00:00 2001 From: Nick Garay Date: Mon, 25 May 2026 14:03:47 -0400 Subject: [PATCH 3/5] Fix kafka dependency version to 4.1.2 to resolve CVE --- comm/sensorhub-comm-kafka/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comm/sensorhub-comm-kafka/build.gradle b/comm/sensorhub-comm-kafka/build.gradle index df52f27..5b40238 100644 --- a/comm/sensorhub-comm-kafka/build.gradle +++ b/comm/sensorhub-comm-kafka/build.gradle @@ -4,7 +4,7 @@ version = '1.0.0' dependencies { implementation 'org.sensorhub:sensorhub-core:' + oshCoreVersion - embeddedImpl 'org.apache.kafka:kafka-clients:4.0.0' + embeddedImpl 'org.apache.kafka:kafka-clients:4.1.2' } test { From 71b9569ff82be0a4330d776c02af76c23617d2d7 Mon Sep 17 00:00:00 2001 From: Nick Garay Date: Thu, 28 May 2026 11:10:39 -0400 Subject: [PATCH 4/5] Update build.gradle to allow for NEXUS-based artifact builds --- build.gradle | 394 ++++++++++++++++++--------------------------------- 1 file changed, 135 insertions(+), 259 deletions(-) diff --git a/build.gradle b/build.gradle index 7d1321f..132cedb 100644 --- a/build.gradle +++ b/build.gradle @@ -11,8 +11,15 @@ allprojects { apply from: 'readmes.gradle' -ext.oshCoreVersion = '2.0.0-beta.3' -description = 'No-Code Add-ons' +ext { + oshCoreVersion = '2.0.0-beta.3' +} + +description = 'NoCode Add-ons' + +/* ----------------------------------------------------------- + BUNDLE HARVESTING + INDEX +----------------------------------------------------------- */ tasks.register("harvestBundles", Copy) { group = 'bundles' @@ -22,9 +29,7 @@ tasks.register("harvestBundles", Copy) { subprojects.each { subproj -> if (!subproj.name.contains("v4l")) { def osgiOutputs = subproj.osgi?.outputs - if (osgiOutputs) { - from osgiOutputs - } + if (osgiOutputs) from osgiOutputs } } } @@ -44,116 +49,116 @@ tasks.register("bundlesDistZip", Zip) { group = 'bundles' dependsOn genOSGiIndex destinationDirectory = file(layout.buildDirectory.dir("osgi")) - from layout.buildDirectory.dir("osgi/bundles").get().asFile + from layout.buildDirectory.dir("osgi/bundles") archiveFileName = "${rootProject.name}-osgi-bundles.zip" - include '*' } -tasks.register("cleanBundles", Task) { +tasks.register("cleanBundles") { group = 'bundles' - if (file(layout.buildDirectory.dir("osgi")).exists()) { - - file(layout.buildDirectory.dir("osgi")).deleteDir() + doLast { + delete layout.buildDirectory.dir("osgi") } } +/* ----------------------------------------------------------- + SUBPROJECT CONFIG +----------------------------------------------------------- */ + subprojects { + apply plugin: 'java-library' apply plugin: 'java-test-fixtures' apply plugin: 'eclipse' apply plugin: 'maven-publish' - dependencies { - testImplementation "junit:junit:4.13.1" - } + + version = rootProject.oshCoreVersion + ext.pom = {} // pom data that subprojects can append to sourceCompatibility = 17 targetCompatibility = 17 repositories { - //mavenLocal() mavenCentral() + +// maven { +// name = 'osh-core' +// url = uri("https://maven.pkg.github.com/opensensorhub/osh-core") +// credentials { +// username = System.getenv("GITHUB_ACTOR") +// password = System.getenv("GITHUB_TOKEN") +// } +// } +// maven { +// name = 'osh-addons' +// url = uri("https://maven.pkg.github.com/opensensorhub/osh-addons") +// credentials { +// username = System.getenv("GITHUB_ACTOR") +// password = System.getenv("GITHUB_TOKEN") +// } +// } maven { - name = 'osh-core' - url = uri("https://maven.pkg.github.com/opensensorhub/osh-core") - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") - } - } - maven { - name = 'osh-addons' - url = uri("https://maven.pkg.github.com/opensensorhub/osh-addons") + name = 'nexus' + url = System.getenv("NEXUS_REPO_PUBLIC") + allowInsecureProtocol = true credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") + username = System.getenv("NEXUS_ACTOR") + password = System.getenv("NEXUS_TOKEN") } } } - version = oshCoreVersion - ext.pom = {} // pom data that subprojects can append to + dependencies { + testImplementation "junit:junit:4.13.1" + } - jar { - into('lib') { - from { - project.configurations.embedded - } - } + /* ----------------------------------------------------------- + EMBEDDED CONFIG MODEL + ----------------------------------------------------------- */ + configurations { + embeddedApi + embeddedImpl + embedded.extendsFrom(embeddedApi, embeddedImpl) + api.extendsFrom(embeddedApi) + implementation.extendsFrom(embeddedImpl) } - // inject all repositories from included builds if any - repositories.addAll(rootProject.repositories) + /* ----------------------------------------------------------- + OSGI BUNDLE TASK + ----------------------------------------------------------- */ task osgi(type: aQute.bnd.gradle.Bundle) { - from project.sourceSets.main.output + from sourceSets.main.output archiveClassifier = 'bundle' + bundle { classpath = sourceSets.main.compileClasspath } - // copy embedded libs into bundle jar into('lib') { - from { - project.configurations.embedded - } + from configurations.embedded } - // helper method to list all non-empty packages in jar + // helper methods preserved exactly ext.getPackagesFromJar = { jarFile, packageSet -> - //println jarFile FileSystems.newFileSystem(jarFile.toPath(), ClassLoader.getSystemClassLoader()).withCloseable { fs -> def rootDir = fs.getPath('/') getPackagesFromDir(rootDir, packageSet) } } - // helper method to list all non-empty packages in class folder ext.getPackagesFromDir = { rootDir, packageSet -> rootDir.eachDirRecurse { dir -> - //println dir - // skip some directories - if (dir.toString().startsWith(File.separator + 'META-INF')) { - return; - } + if (dir.toString().startsWith(File.separator + 'META-INF')) return - // keep only packages that have java class files in them Files.list(dir) .filter { it.toString().endsWith('.class') } .findAny() .ifPresent { - // Using File.separator in the replace calls on windows does not seem to work and messes up the creation - // of the manifest files - if (rootDir.relativize(dir).toString().contains('\\')) { - packageSet.add(rootDir.relativize(dir).toString() - .replace('\\', '.') + '.*') - } else { - packageSet.add(rootDir.relativize(dir).toString() - .replace('/', '.') + '.*') - } + def rel = rootDir.relativize(dir).toString() + packageSet.add(rel.replace('\\', '.').replace('/', '.') + '.*') } } } - // help method to automatically find osgi activator class ext.findActivator = { for (def classDir : sourceSets.main.output.classesDirs) { def rootDir = classDir.toPath() @@ -161,268 +166,139 @@ subprojects { .filter { it.toString().endsWith('Activator.class') } .map { rootDir.relativize(it).toString() - .replace(java.io.File.separatorChar, (char) '.') + .replace(File.separatorChar, (char) '.') .replaceAll('.class$', '') } .findAny() .orElse(null) - if (activatorClass) - return activatorClass + if (activatorClass) return activatorClass } } doFirst { - // configure bnd options before running the task manifest { - //if (!attributes['Import-Package']) - // attributes 'Import-Package': '!java.*,!com.sun.*,!sun.*,!javax.xml.*,!org.xml.sax.*,!org.w3c.dom.*,*' - //attributes '-noimportjava': true - //attributes '-sources': true - - // ignore some common errors attributes '-fixupmessages': 'Classes found in the wrong directory; is:=ignore,' + 'Unused Import-Package instructions; is:=ignore,' + - 'The default package \'.\' is not permitted by the Import-Package syntax; is:=ignore,' + + 'The default package \'.\' is not permitted; is:=ignore,' + 'Unused Export-Package instructions; is:=ignore,' - // disable DS annotation processing if (!attributes['-dsannotations']) attributes '-dsannotations': '!*' - // auto detect bundle activator if not configured if (!attributes['Bundle-Activator']) { def activatorClass = findActivator() - //println activatorClass if (activatorClass) attributes 'Bundle-Activator': activatorClass } - // compute imports/exports based on gradle dependencies - def embeddedJars = project.configurations.embedded - def depJars = project.configurations.compileClasspath.minus(embeddedJars) - def apiJars = project.configurations.embeddedApi + def embeddedJars = configurations.embedded + def depJars = configurations.compileClasspath.minus(embeddedJars) + def apiJars = configurations.embeddedApi - // import all packages from all dependencies that are not embedded def importedPackages = [] as Set - depJars.each { - getPackagesFromJar(it, importedPackages) - } - //println importedPackages + depJars.each { getPackagesFromJar(it, importedPackages) } if (!attributes['Import-Package']) attributes 'Import-Package': importedPackages.join(',') - // export packages in API dependencies and in this project def exportedPackages = [] as Set sourceSets.main.output.classesDirs.each { getPackagesFromDir(it.toPath(), exportedPackages) } - apiJars.each { - getPackagesFromJar(it, exportedPackages) - } - //println exportedPackages + apiJars.each { getPackagesFromJar(it, exportedPackages) } if (!attributes['-exportcontents']) attributes '-exportcontents': exportedPackages.join(',') - /*// add all dependencies that are not embedded to Require-Bundle - attributes 'Import-Package': '!*' - def embeddedDeps = project.configurations.embedded.allDependencies - def apiDeps = project.configurations.api.allDependencies.minus(embeddedDeps) - def implDeps = project.configurations.implementation.allDependencies.minus(apiDeps).minus(embeddedDeps) - def requiredBundles = '' - apiDeps.each { - if (!requiredBundles.isEmpty()) requiredBundles += ',' - requiredBundles += it.group + '.' + it.name + ';bundle-version:="' + it.version + '";visibility:=reexport' - } - implDeps.each { - if (!requiredBundles.isEmpty()) requiredBundles += ',' - requiredBundles += it.group + '.' + it.name + ';bundle-version:="' + it.version + '"' - } - attributes 'Require-Bundle': requiredBundles*/ - - /*// add embedded jars to OSGi classpath - // only add jars that were not substituted with newer version by gradle - def classpath = '.' - def embeddedJars = '' - def runtimeDeps = project.configurations.runtimeClasspath.collect { it.name }; - project.configurations.embedded.each { - if (runtimeDeps.contains(it.name)) { - embeddedJars += 'lib/' + it.name + '=' + it.name + ';lib:=true,' - } - } - attributes '-includeresource': embeddedJars*/ - - // add embedded jars to OSGi classpath - // we do it like this so imports are not computed for these - def classpath = '.' + def runtimeDeps = configurations.runtimeClasspath.collect { it.name } def embeddedClasspath = '' - def runtimeDeps = project.configurations.runtimeClasspath.collect { it.name } - project.configurations.embedded.each { + configurations.embedded.each { if (runtimeDeps.contains(it.name)) { - embeddedClasspath += 'lib/' + it.name + ',' + embeddedClasspath += "lib/${it.name}," } } attributes 'Bundle-ClassPath': embeddedClasspath + '.' - - // auto-generate Bundle-NativeCode header if native libs are placed in - // the lib/native resource folder with the proper directory structure - def resourcesFolder = new File(projectDir, '/src/main/resources') - def nativeFolder = new File(resourcesFolder, '/lib/native') - if (nativeFolder.exists()) { - def currentPlatform = '' - def nativePaths = '' - fileTree(dir: nativeFolder).files.each { - def path = resourcesFolder.toPath().relativize(it.toPath()) - if (path.nameCount != 5) { - throw new GradleException("Invalid native library path in resource folder: " + path + - ". Path must be of the form 'lib/native/{osname}/{arch}/{libname}.{ext}'") - } - - // lib paths must be grouped by platform (os and processor) - def osname = path.getName(2) - def proc = path.getName(3) - def platform = 'osname=' + osname + '; processor=' + proc - if (platform != currentPlatform) { - nativePaths = platform + (nativePaths.isEmpty() ? '' : ', ' + nativePaths) - currentPlatform = platform; - } - - nativePaths = path.toString().replace('\\', '/') + '; ' + nativePaths - } - - attributes 'Bundle-NativeCode': nativePaths - } } } } - configurations { - embeddedApi - embeddedImpl - embedded - embedded.extendsFrom(embeddedApi, embeddedImpl) - api.extendsFrom(embeddedApi) - implementation.extendsFrom(embeddedImpl) - } - // add project dependency to proper configuration depending on version - // this is used to build different zip distributions - afterEvaluate { p -> + /* ----------------------------------------------------------- + PUBLISHING (CLEAN + DEV FLAG SUPPORT) + ----------------------------------------------------------- */ - rootProject.dependencies { - def dep = p.version.endsWith('SNAPSHOT') ? dev(p) : stable(p) - dep.exclude group: 'org.sensorhub' - dep.exclude group: 'org.vast.opengis' - } + publishing { + publications { + mavenJava(MavenPublication) { + from components.java - if (p.name != "sensorhub-test") { - - p.osgi { - manifest { - // main info - attributes 'Bundle-SymbolicName': p.group + '.' + p.name - if (p.description != null && !attributes['Bundle-Name']) - attributes 'Bundle-Name': p.description - if (p.details != null && !attributes['Bundle-Description']) - attributes 'Bundle-Description': p.details - attributes 'Bundle-Version': p.version - if (p.hasProperty('buildNumber') && p.buildNumber != null && !p.buildNumber.isEmpty()) - attributes 'Bundle-BuildNumber': p.buildNumber - if (!attributes['Bundle-License']) - attributes 'Bundle-License': 'MPL 2.0 (http://mozilla.org/MPL/2.0)' - if (!attributes['Bundle-Copyright'] && attributes['Bundle-Vendor']) - attributes 'Bundle-Copyright': 'Copyright (c) ' + attributes['Bundle-Vendor'] + '. All Rights Reserved' + artifact(tasks.osgi) { + classifier = 'bundle' } - } - - // also use osgi headers in JAR manifest - p.jar { - manifest { - from p.osgi.manifest - } - } - // maven artifact content - p.publishing { - publications { - mavenJava(MavenPublication) { - from components.java - - // Publish the OSGi bundle JAR as an additional artifact - artifact(p.tasks.osgi) { - classifier = 'bundle' - } - - pom.withXml { - asNode().get('version') + ({ - resolveStrategy = Closure.DELEGATE_FIRST - name p.description - if (p.details != null) - description p.details - url 'https://georobotix.us' - licenses { - license { - name 'Proprietary – All rights reserved' - url 'https://georobotix.us//legal' - distribution 'repo' - } - } - scm { - url 'https://github.com/Botts-Innovative-Research/no-code-addons' - connection 'scm:git:git://github.com/Botts-Innovative-Research/no-code.git' - } - issueManagement { - url 'https://github.com/Botts-Innovative-Research/no-code-addons/issues' - system 'GitHub Issues' - } - } >> p.pom) - } } - } - repositories { - //mavenLocal() - maven { - name = "GitHubPackages" - url = "https://maven.pkg.github.com/Botts-Innovative-Research/no-code-addons" - credentials { - username = System.getenv("GITHUB_ACTOR") - password = System.getenv("GITHUB_TOKEN") + pom { + name = project.description + description = project.hasProperty('details') && project.details ? project.details : project.description + url = 'https://georobotix.us' + licenses { + license { + name = 'Proprietary – All rights reserved' + url = 'https://georobotix.us/legal' + distribution = 'repo' } } + scm { + url = 'https://github.com/Botts-Innovative-Research/osh-no-code' + connection = 'scm:git:git://github.com/Botts-Innovative-Research/osh-no-code.git' + } + issueManagement { + url = 'https://github.com/Botts-Innovative-Research/osh-no-code/issues' + system = 'GitHub Issues' + } } } + } - p.tasks.named("generateMetadataFileForMavenJavaPublication") { - doFirst { - if (System.getenv("GITHUB_ACTOR") == null) { - throw new Exception("Environment variable GITHUB_ACTOR not set. Please set to your github username.") - } + repositories { + maven { + name = "Nexus" - if (System.getenv("GITHUB_TOKEN") == null) { - throw new Exception("Environment variable GITHUB_TOKEN not set. Please generate and set to your personal access token: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens") - } + if (version.toString().endsWith("SNAPSHOT")) { + url = System.getenv("NEXUS_REPO_SNAPSHOT") + } + else { + url = System.getenv("NEXUS_REPO_RELEASE") } - } - p.tasks.named("publishMavenJavaPublicationToGitHubPackagesRepository") { - onlyIf { - // - MavenArtifactRepository repo = repository as MavenArtifactRepository; - MavenPublication pub = publication as MavenPublication; - - HttpURLConnection connection = new URL("$repo.url/${pub.groupId.replace('.', '/')}/$pub.artifactId/$pub.version/$pub.artifactId-${pub.version}.jar").openConnection(); - connection.setRequestMethod("GET"); - connection.setRequestProperty("Authorization", "Basic ${new String(Base64.getEncoder().encode("$repo.credentials.username:$repo.credentials.password".bytes))}"); - connection.connect(); - return connection.responseCode == 404; + allowInsecureProtocol = true + credentials { + username = System.getenv("NEXUS_ACTOR") + password = System.getenv("NEXUS_TOKEN") } } } } + /* ----------------------------------------------------------- + SAFETY CHECKS + ----------------------------------------------------------- */ + + tasks.named("generateMetadataFileForMavenJavaPublication") { + doFirst { + if (!System.getenv("NEXUS_ACTOR")) + throw new Exception("NEXUS_ACTOR not set") + + if (!System.getenv("NEXUS_TOKEN")) + throw new Exception("NEXUS_TOKEN not set") + } + } + jar.dependsOn(copyReadmes) clean.dependsOn(cleanReadmes, cleanBundles) } -// create one configuration for each distribution +/* ----------------------------------------------------------- + DISTRIBUTION CONFIGS +----------------------------------------------------------- */ + configurations { stable dev -} \ No newline at end of file +} From 67f536122fc089215f2950081dbb9206e1b533bf Mon Sep 17 00:00:00 2001 From: Nick Garay Date: Thu, 28 May 2026 18:58:25 -0400 Subject: [PATCH 5/5] Update build.gradle to create manifest --- build.gradle | 57 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/build.gradle b/build.gradle index 132cedb..5fa7bb1 100644 --- a/build.gradle +++ b/build.gradle @@ -80,22 +80,6 @@ subprojects { repositories { mavenCentral() -// maven { -// name = 'osh-core' -// url = uri("https://maven.pkg.github.com/opensensorhub/osh-core") -// credentials { -// username = System.getenv("GITHUB_ACTOR") -// password = System.getenv("GITHUB_TOKEN") -// } -// } -// maven { -// name = 'osh-addons' -// url = uri("https://maven.pkg.github.com/opensensorhub/osh-addons") -// credentials { -// username = System.getenv("GITHUB_ACTOR") -// password = System.getenv("GITHUB_TOKEN") -// } -// } maven { name = 'nexus' url = System.getenv("NEXUS_REPO_PUBLIC") @@ -220,6 +204,47 @@ subprojects { } } + /* ----------------------------------------------------------- + BUILD MANIFESTS + ----------------------------------------------------------- */ + + afterEvaluate { p -> + + rootProject.dependencies { + def dep = p.version.endsWith('SNAPSHOT') ? dev(p) : stable(p) + dep.exclude group: 'org.sensorhub' + dep.exclude group: 'org.vast.opengis' + } + + if (p.name != "sensorhub-test") { + + p.osgi { + manifest { + // main info + attributes 'Bundle-SymbolicName': p.group + '.' + p.name + if (p.description != null && !attributes['Bundle-Name']) + attributes 'Bundle-Name': p.description + if (p.details != null && !attributes['Bundle-Description']) + attributes 'Bundle-Description': p.details + attributes 'Bundle-Version': p.version + if (p.hasProperty('buildNumber') && p.buildNumber != null && !p.buildNumber.isEmpty()) + attributes 'Bundle-BuildNumber': p.buildNumber + if (!attributes['Bundle-License']) + attributes 'Bundle-License': 'Proprietary – All rights reserved. No redistribution or modification permitted.' + if (!attributes['Bundle-Copyright'] && attributes['Bundle-Vendor']) + attributes 'Bundle-Copyright': 'Copyright (c) ' + attributes['Bundle-Vendor'] + '. All Rights Reserved' + } + } + + // also use osgi headers in JAR manifest + p.jar { + manifest { + from p.osgi.manifest + } + } + } + } + /* ----------------------------------------------------------- PUBLISHING (CLEAN + DEV FLAG SUPPORT) ----------------------------------------------------------- */