@@ -188,7 +188,7 @@ export class AtomicServer {
188188 }
189189
190190 @func ( )
191- rustBuild ( ) : Container {
191+ rustBuild ( @ argument ( ) release : boolean = false ) : Container {
192192 const source = this . source ;
193193 const cargoCache = dag . cacheVolume ( "cargo" ) ;
194194
@@ -220,14 +220,25 @@ export class AtomicServer {
220220 browserDir
221221 ) ;
222222
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+
223233 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 ) ;
231242 }
232243
233244 @func ( )
@@ -265,7 +276,8 @@ export class AtomicServer {
265276 . from ( RUST_IMAGE )
266277 . withExec ( [ "cargo" , "install" , "cross" ] )
267278 . withMountedDirectory ( "/code" , source )
268- . withWorkdir ( "/code" ) ;
279+ . withWorkdir ( "/code" )
280+ . withExec ( [ "rustup" , "target" , "add" , target ] ) ;
269281
270282 return rustContainer
271283 . withExec ( [ "cross" , "build" , "--target" , target , "--release" ] )
@@ -355,4 +367,88 @@ export class AtomicServer {
355367
356368 return deployUrl ;
357369 }
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+ }
358454}
0 commit comments