@@ -188,7 +188,7 @@ export class AtomicServer {
188
188
}
189
189
190
190
@func ( )
191
- rustBuild ( ) : Container {
191
+ rustBuild ( @ argument ( ) release : boolean = false ) : Container {
192
192
const source = this . source ;
193
193
const cargoCache = dag . cacheVolume ( "cargo" ) ;
194
194
@@ -220,14 +220,25 @@ export class AtomicServer {
220
220
browserDir
221
221
) ;
222
222
223
+ const buildArgs = release
224
+ ? [ "cargo" , "build" , "--release" ]
225
+ : [ "cargo" , "build" ] ;
226
+ const binaryPath = release
227
+ ? "./target/release/atomic-server"
228
+ : "./target/debug/atomic-server" ;
229
+ const targetPath = release
230
+ ? "/code/target/release/atomic-server"
231
+ : "/code/target/debug/atomic-server" ;
232
+
223
233
return containerWithAssets
224
- . withExec ( [ "cargo" , "build" ] )
225
- . withExec ( [ "./target/release/atomic-server" , "--version" ] )
226
- . withExec ( [
227
- "cp" ,
228
- "/code/target/release/atomic-server" ,
229
- "/atomic-server-binary" ,
230
- ] ) ;
234
+ . withExec ( buildArgs )
235
+ . withExec ( [ binaryPath , "--version" ] )
236
+ . withExec ( [ "cp" , targetPath , "/atomic-server-binary" ] ) ;
237
+ }
238
+
239
+ @func ( )
240
+ rustReleaseBuild ( ) : Container {
241
+ return this . rustBuild ( true ) ;
231
242
}
232
243
233
244
@func ( )
@@ -265,7 +276,8 @@ export class AtomicServer {
265
276
. from ( RUST_IMAGE )
266
277
. withExec ( [ "cargo" , "install" , "cross" ] )
267
278
. withMountedDirectory ( "/code" , source )
268
- . withWorkdir ( "/code" ) ;
279
+ . withWorkdir ( "/code" )
280
+ . withExec ( [ "rustup" , "target" , "add" , target ] ) ;
269
281
270
282
return rustContainer
271
283
. withExec ( [ "cross" , "build" , "--target" , target , "--release" ] )
@@ -355,4 +367,88 @@ export class AtomicServer {
355
367
356
368
return deployUrl ;
357
369
}
370
+
371
+ @func ( )
372
+ async deployServer (
373
+ @argument ( ) remoteHost : string ,
374
+ @argument ( ) remoteUser : Secret ,
375
+ @argument ( ) sshPrivateKey : Secret
376
+ ) : Promise < string > {
377
+ // Build the cross-compiled binary for x86_64-unknown-linux-musl
378
+ const crossBuildContainer = this . rustCrossBuild (
379
+ "x86_64-unknown-linux-musl"
380
+ ) ;
381
+ const binaryFile = crossBuildContainer . file (
382
+ "/code/target/x86_64-unknown-linux-musl/release/atomic-server"
383
+ ) ;
384
+
385
+ // Create deployment container with SSH client
386
+ const deployContainer = dag
387
+ . container ( )
388
+ . from ( "alpine:latest" )
389
+ . withExec ( [ "apk" , "add" , "--no-cache" , "openssh-client" , "rsync" ] )
390
+ . withFile ( "/atomic-server-binary" , binaryFile , { permissions : 0o755 } ) ;
391
+
392
+ // Setup SSH key
393
+ const sshContainer = deployContainer
394
+ . withExec ( [ "mkdir" , "-p" , "/root/.ssh" ] )
395
+ . withSecretVariable ( "SSH_PRIVATE_KEY" , sshPrivateKey )
396
+ . withExec ( [ "sh" , "-c" , 'echo "$SSH_PRIVATE_KEY" > /root/.ssh/id_rsa' ] )
397
+ . withExec ( [ "chmod" , "600" , "/root/.ssh/id_rsa" ] )
398
+ . withExec ( [ "ssh-keyscan" , "-H" , remoteHost ] )
399
+ . withExec ( [
400
+ "sh" ,
401
+ "-c" ,
402
+ `ssh-keyscan -H ${ remoteHost } >> /root/.ssh/known_hosts` ,
403
+ ] ) ;
404
+
405
+ // Transfer binary using rsync
406
+ const transferResult = await sshContainer
407
+ . withSecretVariable ( "REMOTE_USER" , remoteUser )
408
+ . withExec ( [
409
+ "sh" ,
410
+ "-c" ,
411
+ `rsync -rltgoDzvO /atomic-server-binary $REMOTE_USER@${ remoteHost } :~/atomic-server-x86_64-unknown-linux-musl` ,
412
+ ] )
413
+ . stdout ( ) ;
414
+
415
+ // Execute deployment commands on remote server
416
+ const deployResult = await sshContainer
417
+ . withSecretVariable ( "REMOTE_USER" , remoteUser )
418
+ . withExec ( [
419
+ "sh" ,
420
+ "-c" ,
421
+ `ssh -i /root/.ssh/id_rsa $REMOTE_USER@${ remoteHost } '
422
+ mv ~/atomic-server-x86_64-unknown-linux-musl ~/atomic-server &&
423
+ cp ~/atomic-server ~/atomic-server-$(date +"%Y-%m-%dT%H:%M:%S") &&
424
+ systemctl stop atomic &&
425
+ ./atomic-server export &&
426
+ systemctl start atomic &&
427
+ systemctl status atomic
428
+ '` ,
429
+ ] )
430
+ . stdout ( ) ;
431
+
432
+ return `Deployment to ${ remoteHost } completed successfully:\n${ deployResult } ` ;
433
+ }
434
+
435
+ @func ( )
436
+ async deployStaging (
437
+ @argument ( ) remoteUser : Secret ,
438
+ @argument ( ) sshPrivateKey : Secret
439
+ ) : Promise < string > {
440
+ return this . deployServer (
441
+ "staging.atomicdata.dev" ,
442
+ remoteUser ,
443
+ sshPrivateKey
444
+ ) ;
445
+ }
446
+
447
+ @func ( )
448
+ async deployProduction (
449
+ @argument ( ) remoteUser : Secret ,
450
+ @argument ( ) sshPrivateKey : Secret
451
+ ) : Promise < string > {
452
+ return this . deployServer ( "atomicdata.dev" , remoteUser , sshPrivateKey ) ;
453
+ }
358
454
}
0 commit comments