-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathant-replacement.gradle
254 lines (237 loc) · 8.22 KB
/
ant-replacement.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
// This file intends to replace the build.xml content of FRC.
// It may need to be updated when FRC build.xml updates occur.
buildscript {
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
maven {
name "gradle plugins"
url "http://dl.bintray.com/gradle/gradle-plugins"
}
}
dependencies {
classpath 'com.squareup.okhttp3:okhttp:3.5.0'
classpath 'org.hidetake:gradle-ssh-plugin:2.7.2'
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
}
}
apply plugin: org.hidetake.gradle.ssh.plugin.SshPlugin
apply plugin: com.github.jengelman.gradle.plugins.shadow.ShadowPlugin
// === Build properties === //
ext {
currentVersion = 'current'
wpilib = System.getProperty('user.home') + "/wpilib/java/${currentVersion}"
wpilibAntDir = "${wpilib}/ant"
wpiUser = 'lvuser'
wpiUserHome = "/home/${wpiUser}"
robotPackage = "org.usfirst.frc.team${project.packageNumber}.robot"
robotClass = "${robotPackage}.Robot"
taskGroup = "RoboRIO"
}
// === End B properties === //
// Setup a jar
jar {
manifest {
attributes(
"Main-Class": 'edu.wpi.first.wpilibj.RobotBase',
"Robot-Class": project.robotClass,
"Class-Path": '.'
)
}
}
// isReachable test
boolean isReachable(String addr, int openPort, int timeOutMillis) {
try {
new Socket().withCloseable { soc ->
soc.connect(new InetSocketAddress(addr, openPort), timeOutMillis);
}
return true;
} catch (IOException ex) {
return false;
}
}
boolean canReachSSH(String addr) {
return isReachable(addr, 22, 100);
}
if (!project.hasProperty('teamNumber')) {
println "No team number provided."
throw new AssertionError("No team number.");
}
ext.teamNumberInt = project.property('teamNumber') as Integer
ext.noDnsIp = project.hasProperty('noDnsIp') ? project.property('noDnsIp') : '169.254.204.184'
List<String> getStaticIps() {
if (project.hasProperty("staticIP")) {
if (project.staticIP in List) {
return project.staticIP
}
return [project.staticIP]
}
// Try each of these -- it's cheap
def possibleIps = [2, 25, 30, 91]
int top = teamNumberInt / 100
int lower = teamNumberInt % 100
return (possibleIps.collect { lowBit -> "10.${top}.${lower}.${lowBit}" }) + project.noDnsIp
}
class RobotIp {
String ip
String description
}
boolean tryRobotIp(RobotIp ip) {
print "Trying to reach robot via ${ip.ip} (${ip.description})... "
if (!canReachSSH(ip.ip)) {
println "Failed to reach robot via ${ip.description}."
return false
}
println "Found robot via ${ip.description}."
return true
}
task initializeRobotIP() {
group taskGroup
description 'Discovers the robot\'s IP or fails'
}
initializeRobotIP.doLast {
def ips = [
new RobotIp(ip: "roboRIO-${teamNumberInt}-FRC.local", description: "FRC.local DNS"),
new RobotIp(ip: "roboRIO-${teamNumberInt}-FRC.lan", description: "FRC.lan DNS"),
new RobotIp(ip: "172.22.11.2", description: "USB Connection"),
] + (getStaticIps().indexed().collect { num, ip ->
new RobotIp(ip: ip, description: "Static IP #$num")
})
def ipStack = new ArrayDeque(ips)
String robotIP = ""
while (!ipStack.isEmpty()) {
def ip = ipStack.pop()
if (tryRobotIp(ip)) {
robotIP = ip.ip
break
}
}
if (robotIP.isEmpty()) {
println "Unable to reach the robot."
throw new AssertionError("Unable to reach the robot.")
}
project.ext.robotIP = robotIP
project.remotes.create('robot') {
host = robotIP
user = project.wpiUser
password = ''
knownHosts = allowAnyHosts
}
project.remotes.create('robotAdmin') {
host = robotIP
user = 'admin'
password = ''
knownHosts = allowAnyHosts
}
}
// It's best to compile first.
initializeRobotIP.shouldRunAfter jar
initializeRobotIP.shouldRunAfter shadowJar
import okhttp3.*;
task checkSysProps(dependsOn: [initializeRobotIP]) {
group taskGroup
description 'Checks the roboRIO image version.'
}
checkSysProps.doLast {
def XML = MediaType.parse("text/xml; charset=utf-16le");
def client = new OkHttpClient();
def body = new FormBody.Builder()
.add('Function', 'GetPropertiesOfItem')
.add('Plugins', 'nisyscfg')
.add('Items', 'system')
.build();
Request request = new Request.Builder()
.url("http://${project.robotIP}/nisysapi/server")
.post(body)
.build();
Response response = client.newCall(request).execute();
def hexemell = response.body().string();
def roboRioImageMatch = hexemell =~ /FRC_roboRIO_[0-9]+_v([0-9]+)/
if (!roboRioImageMatch) {
throw new IllegalStateException("Image version not found.");
}
def roboRioYearMatch = hexemell =~ /FRC_roboRIO_([0-9]+)_v/
if (!roboRioYearMatch) {
throw new IllegalStateException("Year not found.");
}
def allowedImage = '8'
def image = roboRioImageMatch.group(1)
if (!allowedImage.contains(image)) {
throw new IllegalStateException("roboRIO Image does not match plugin, allowed image version: ${allowedImage}");
}
def allowedYear = '2017'
def year = roboRioYearMatch.group(1)
if (!allowedYear.contains(year)) {
throw new IllegalStateException("roboRIO Year does not match plugin, allowed year: ${allowedYear}");
}
println 'roboRIO image version validated'
}
task checkJRE(dependsOn: [initializeRobotIP]) {
group taskGroup
description 'Checks the JRE of the roboRIO'
}
checkJRE.doLast {
ssh.run {
session(remotes.robot) {
execute 'test -d /usr/local/frc/JRE'
}
}
println 'Found JRE.'
}
task checkRoboRIO(dependsOn: [checkSysProps, checkJRE]) {
group taskGroup
// Just a splitter for the sub-tasks.
description 'Checks that the roboRIO is what we expect.'
}
// Defines deploy tasks for regular and debug deploys.
void defineDeployTask(Object project, boolean debug) {
def task = project.tasks.create(name: 'deploy' + (debug ? 'Debug' : ''),
dependsOn: [shadowJar, checkRoboRIO]) {
group taskGroup
description "Deploys the jar to the robot. ${debug ? 'Waits' : 'Does not wait'} for a debugger."
ext.jarFile = project.shadowJar.archivePath
ext.netConsoleHost = "${project.wpilibAntDir}/netconsole-host"
ext.commandFile = "${project.wpilibAntDir}/robot${debug ? 'Debug' : ''}Command"
ext.natives = files(fileTree("libs/native").files)
ext.nativesTarget = "/usr/local/frc/lib"
inputs.file jarFile
inputs.file commandFile
inputs.dir natives
if (debug) {
ext.frcDebugFile = "${project.wpilibAntDir}/frcdebug"
inputs.file frcDebugFile
}
}
task.doLast {
ssh.run {
session(remotes.robotAdmin) {
//println "Copying natives"
//put from: natives, into: nativesTarget
//put from: netConsoleHost, into: "/usr/local/frc/bin/"
//execute 'chmod +x /usr/local/frc/bin/netconsole-host'
//execute 'chmod -R +x /usr/local/frc/lib'
//execute 'ldconfig', ignoreError: true
}
session(remotes.robot) {
println "Copying jar"
put from: jarFile, into: "${project.wpiUserHome}/FRCUserProgram.jar"
execute 'killall -q netconsole-host', ignoreError: true
put from: commandFile, into: project.wpiUserHome
if (debug) {
println "Setting debug flag"
put from: frcDebugFile, into: '/tmp/frcdebug'
execute 'chown lvuser:ni /tmp/frcdebug'
}
println "Starting program"
execute '. /etc/profile.d/natinst-path.sh; /usr/local/frc/bin/frcKillRobot.sh -t -r', ignoreError: true
if (!debug) {
execute 'sync'
}
}
}
}
}
defineDeployTask(project, false)
defineDeployTask(project, true)