Repository navigation
Expand file tree
/
Copy pathbuild.gradle.kts
More file actions
141 lines (121 loc) · 5.76 KB
/
Copy pathbuild.gradle.kts
File metadata and controls
141 lines (121 loc) · 5.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
plugins {
base
id("io.ia.sdk.modl") version "0.5.0"
id("com.github.spotbugs") version "6.4.8" apply false
id("org.owasp.dependencycheck") version "12.2.0" apply false
}
// ── OWASP Dependency Check ──────────────────────────────────────────────────
apply(plugin = "org.owasp.dependencycheck")
configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> {
failBuildOnCVSS = 7.0f
formats = listOf("HTML", "JSON")
analyzers.assemblyEnabled = false
}
version = "4.6.4"
group = "com.gaskony"
allprojects {
version = rootProject.version
group = "com.gaskony"
}
ignitionModule {
// Include version in filename for version control
fileName.set("Python3-${project.version}")
name.set("Python 3 Integration")
id.set("com.gaskony.python3")
moduleVersion.set(project.version.toString())
moduleDescription.set("Python 3 Integration for Ignition - Gateway Web UI (React) + Designer Script Console (Java Swing). Developed by Gaskony.")
requiredIgnitionVersion.set("8.3.0")
requiredFrameworkVersion.set("8")
// Free module - no license required
freeModule.set(true)
projectScopes.putAll(
mapOf(
":common" to "GD",
":gateway" to "G",
":designer" to "D" // Designer scope for Python 3 IDE (v1.7.0+, REST API communication)
)
)
hooks.putAll(
mapOf(
"com.gaskony.python3.gateway.GatewayHook" to "G",
"com.gaskony.python3.designer.DesignerHook" to "D" // Designer hook for IDE UI
)
)
// Module signing configuration
// Auto-skips signing when the keystore file does not exist (e.g. in CI without secrets).
// To sign locally, set ignition.signing.keystoreFile in gradle.properties.
val keystoreFilePath = (findProperty("ignition.signing.keystoreFile") as? String) ?: ""
skipModlSigning.set(keystoreFilePath.isBlank() || !file(keystoreFilePath).exists())
}
// Note: OWASP dependency check configured at top of file via apply(plugin) + configure<> block
// Sync version across all files that reference it
tasks.register("syncVersion") {
group = "versioning"
description = "Syncs project.version to all files that embed it"
doLast {
val ver = project.version.toString()
fun sync(f: File, pattern: Regex, replacement: String) {
if (!f.exists()) return
val text = f.readText()
val updated = text.replace(pattern, replacement)
if (updated != text) { f.writeText(updated); logger.lifecycle(" synced ${f.name} → $ver") }
}
sync(file("web-ui/package.json"),
Regex(""""version":\s*"[^"]+""""), """"version": "$ver"""")
sync(file("README.md"),
Regex("""version-[\d.]+-blue"""), "version-${ver}-blue")
sync(file("README.md"),
Regex("""Python3-[\d.]+\.modl"""), "Python3-${ver}.modl")
sync(file("CLAUDE.md"),
Regex("""Production-ready v[\d.]+"""), "Production-ready v${ver}")
sync(file("CLAUDE.md"),
Regex("""(?m)\*\*Current Version: v[\d.]+\*\*"""), "**Current Version: v${ver}**")
sync(file("designer/src/main/java/com/gaskony/python3/designer/DesignerHook.java"),
Regex("""return "[\d.]+"; // MODULE_VERSION_FALLBACK"""), """return "$ver"; // MODULE_VERSION_FALLBACK""")
sync(file("web-ui/src/components/Sidebar.tsx"),
Regex("""FALLBACK_MODULE_VERSION = '[\d.]+'"""), "FALLBACK_MODULE_VERSION = '$ver'")
// Common-scope version.properties is on the GD classpath, so it is loaded at
// runtime by BOTH the gateway (MonitoringHandlers.getModuleVersion, which feeds
// the web UI /version endpoint) and the designer (DesignerHook).
// Keeping it in common is the single source of truth — a designer-only copy left
// the gateway endpoint stuck on its hardcoded fallback (see v3.8.1 web-UI bug).
val parts = ver.split(".")
if (parts.size == 3) {
val vp = file("common/src/main/resources/version.properties")
val content = "version.major=${parts[0]}\nversion.minor=${parts[1]}\nversion.patch=${parts[2]}\n"
if (!vp.exists() || vp.readText() != content) {
vp.parentFile.mkdirs()
vp.writeText(content)
logger.lifecycle(" synced ${vp.name} → $ver")
}
} else {
logger.warn("syncVersion: cannot decompose version '$ver' into major.minor.patch — version.properties not written")
}
logger.lifecycle("syncVersion: all files set to $ver")
}
}
tasks.named("assembleModlStructure") {
dependsOn("syncVersion")
}
// ── Static analysis ──────────────────────────────────────────────────────────
subprojects {
plugins.withType<JavaPlugin> {
apply(plugin = "checkstyle")
apply(plugin = "com.github.spotbugs")
configure<CheckstyleExtension> {
toolVersion = "10.26.1"
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
isIgnoreFailures = true
}
configure<com.github.spotbugs.snom.SpotBugsExtension> {
ignoreFailures.set(false)
effort.set(com.github.spotbugs.snom.Effort.MAX)
reportLevel.set(com.github.spotbugs.snom.Confidence.MEDIUM)
excludeFilter.set(rootProject.file("config/spotbugs/exclude.xml"))
}
// Disable SpotBugs on test code — enforce only on production sources
tasks.matching { it.name == "spotbugsTest" }.configureEach {
enabled = false
}
}
}