-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.gradle
255 lines (213 loc) · 8.24 KB
/
build.gradle
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import org.zeroturnaround.exec.ProcessExecutor
import org.zeroturnaround.exec.stream.LogOutputStream
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.JSch
import com.jcraft.jsch.JSchException
import com.jcraft.jsch.Session
import com.jcraft.jsch.SftpException
allprojects {
repositories {
mavenCentral()
// WPILib release repo
maven {
url 'https://frcmaven.wpi.edu/artifactory/release'
}
maven {
url = uri("https://maven.pkg.github.com/Mechanical-Advantage/AdvantageKit")
credentials {
username = "Mechanical-Advantage-Bot"
password = "\u0067\u0068\u0070\u005f\u006e\u0056\u0051\u006a\u0055\u004f\u004c\u0061\u0079\u0066\u006e\u0078\u006e\u0037\u0051\u0049\u0054\u0042\u0032\u004c\u004a\u006d\u0055\u0070\u0073\u0031\u006d\u0037\u004c\u005a\u0030\u0076\u0062\u0070\u0063\u0051"
}
}
}
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.zeroturnaround:zt-exec:1.12'
classpath 'com.jcraft:jsch:0.1.55'
}
}
class Subprocess {
Process process;
String name;
public Subprocess(Process process, String name) {
this.process = process;
this.name = name;
}
}
// The subprocess fails to be terminated if Gradle is killed or build is
// terminated before the sim window is closed
// See https://github.com/gradle/gradle/issues/7603
// This is currently an unavoidable problem
Subprocess execSubprocess(String name, String workingDir, String... command) {
new Subprocess(new ProcessExecutor()
.command(command)
.directory(new File(workingDir))
.redirectOutput(new LogOutputStream() {
@Override
protected void processLine(String line) {
println name + "/OUT: " + line
}
})
.redirectError(new LogOutputStream() {
@Override
protected void processLine(String line) {
println name + "/ERR: " + line
}
})
.start()
.getProcess(),
name)
}
// -------------------------------------------------------------------
// Simulation
void buildRust(String name, String dir) {
int exit = execSubprocess(name, dir, "cargo", "build", "--release").process.waitFor()
if (exit != 0)
throw new GradleScriptException(name + ": build failed", null);
}
Subprocess execRust(String name, String dir) {
execSubprocess(name, dir, "cargo", "run", "--release")
}
Subprocess execJava(String name, String dir, String pathToJar, String... args) {
String s = System.getProperty("file.separator");
String javaCmd = System.getProperty("java.home") + s + "bin" + s + "java";
String[] command = new String[args.length + 3];
command[0] = javaCmd;
command[1] = "-jar";
command[2] = pathToJar;
System.arraycopy(args, 0, command, 3, args.length);
execSubprocess(name, dir, command)
}
// Simulation process:
// Ensure ShuffleLog and TaskManager are built
// Build messenger-server and pathfinding (blocking)
// Run messenger-server and pathfinding in background
// Start the robot code simulation
// After sim closed, stop background tasks
List<Subprocess> parallelProcesses = new ArrayList<>()
task simEverything_begin {
dependsOn ":ShuffleLog:build"
// Ensure robot compiles before starting processes
// This prevents build from failing after processes are launched
dependsOn ":Robot:build"
doLast {
// Run Rust build in separate phase so sim waits for build to finish before launching
// Also allows failing the build if cargo fails to compile
buildRust("Messenger", "Messenger/messenger-server")
buildRust("Pathfinding", "Pathfinding")
// Launch the parallel processes
// This must happen after all build stages that could fail!
parallelProcesses.add(execRust("Messenger", "Messenger/messenger-server"))
parallelProcesses.add(execRust("Pathfinding", "Pathfinding"))
parallelProcesses.add(execJava("ShuffleLog", "ShuffleLog", "build/libs/ShuffleLog-2024.jar", "sim"))
}
}
task sim {
dependsOn ":Robot:simulateJava"
}
task simEverything {
dependsOn ":simEverything_begin"
dependsOn ":Robot:simulateJava"
doLast {
// This will be run after the sim gui is closed
// Stop the background processes
for (subprocess in parallelProcesses) {
Process process = subprocess.process;
process.descendants()
.forEach({it.destroy()})
process.destroy()
println "Stopped background process: " + subprocess.name
}
}
}
// -----------------------------------------------------------------
// Deploy
def ORANGEPI_IP = "10.21.29.6"
def ORANGEPI_USER = "orangepi"
def ORANGEPI_PASS = "orangepi"
void buildRustAarch64(String name, String dir) {
int exit = execSubprocess(
name, dir,
"cross", "build", "--release", "--target", "aarch64-unknown-linux-gnu").process.waitFor()
if (exit != 0)
throw new GradleScriptException(name + ": build failed", null);
}
void execRemoteCommand(Session session, String command) {
println "Remote> " + command
ChannelExec exec = (ChannelExec) session.openChannel("exec");
exec.setCommand(command)
exec.setPty(false)
exec.setAgentForwarding(false)
InputStream is = exec.getInputStream();
exec.connect()
exec.run()
String result = null;
try {
result = is.getText("UTF-8");
} finally {
exec.disconnect()
}
print result
}
Session openRemoteSession(String host, String user, String pass) {
JSch jsch = new JSch();
Session session = jsch.getSession(user, host)
session.setPassword(pass)
Properties sshConfig = new Properties()
sshConfig.put("StrictHostKeyChecking", "no")
sshConfig.put("PreferredAuthentications", "password")
session.setConfig(sshConfig)
try {
session.setTimeout(3000)
session.connect(3000)
} catch (JSchException e) {
throw new GradleScriptException("Failed to connect to " + host, e)
}
session
}
void deployDir(ChannelSftp channel, String path) {
try {
channel.mkdir(path)
println "Created remote directory " + path
} catch (SftpException ignored) {
println("Remote directory " + path + " already exists")
}
}
void deployFile(ChannelSftp channel, String localPath, String remotePath) {
println "Deploying " + remotePath
channel.put(localPath.replace('/' as char, File.separatorChar), remotePath)
}
task deployOrangePi {
dependsOn ":TaskManager:TaskManager-Core:build"
doLast {
buildRustAarch64("Messenger", "Messenger/messenger-server")
buildRustAarch64("Pathfinding", "Pathfinding")
Session session = openRemoteSession(ORANGEPI_IP, ORANGEPI_USER, ORANGEPI_PASS)
execRemoteCommand(session, "sudo systemctl stop taskmanager.service")
execRemoteCommand(session, "sudo systemctl stop messenger.service")
String projectHome = project.projectDir.toString() + "/"
String remoteHome = "/home/" + ORANGEPI_USER + "/"
ChannelSftp sftp = (ChannelSftp) session.openChannel("sftp")
sftp.connect()
deployDir(sftp, remoteHome + "Messenger")
deployFile(sftp, projectHome + "Messenger/messenger-server/target/aarch64-unknown-linux-gnu/release/messenger-server", remoteHome + "Messenger/messenger-server")
deployDir(sftp, remoteHome + "TaskManager")
deployFile(sftp, projectHome + "TaskManager/TaskManager-Core/build/libs/TaskManager-Core-2024.jar", remoteHome + "TaskManager/TaskManager.jar")
deployDir(sftp, remoteHome + "TaskManager/tasks")
deployDir(sftp, remoteHome + "TaskManager/tasks/Pathfinding")
deployFile(sftp, projectHome + "Pathfinding/target/aarch64-unknown-linux-gnu/release/pathfinding", remoteHome + "TaskManager/tasks/Pathfinding/pathfinding")
sftp.disconnect()
execRemoteCommand(session, "sudo systemctl start messenger.service")
execRemoteCommand(session, "sudo systemctl start taskmanager.service")
session.disconnect()
}
}
task deployEverything {
dependsOn ":deployOrangePi"
dependsOn ":Robot:deploy"
}