Skip to Content

예제

deplite 패키지로 실제 자주 쓰이는 흐름을 모았어요.
모든 예제는 dart pub get이 끝난 상태를 가정해요.

External — 트리거 호출

import 'package:deplite/deplite.dart'; final deplite = Deplite(apiToken: const String.fromEnvironment('DEPLITE_API_TOKEN')); final job = await deplite.triggers.run( triggerId: triggerId, params: {'ref': 'main', 'actor': 'sehyun'}, idempotencyKey: 'release-${DateTime.now().millisecondsSinceEpoch}', ); print('${job.jobId} ${job.status}');

External — 파일 올리고 트리거

import 'dart:io'; final uploaded = await deplite.files.upload( file: File('/tmp/app.apk'), cleanupRule: const TtlCleanup(3600), contentType: 'application/vnd.android.package-archive', ); final job = await deplite.triggers.run( triggerId: triggerId, params: {'apkFileId': uploaded.id, 'ref': 'main'}, );

External — Sync 트리거로 결과까지 한 번에

responseMode: sync로 만들어진 트리거를 호출하면 워크플로우 완료까지 기다리고 output까지 그대로 받아요.

final job = await deplite.triggers.run( triggerId: syncTriggerId, params: {'ref': 'v1.2.3'}, ); if (job.timedOut) { // responseTimeoutMs 초과. 워크플로우는 백그라운드에서 계속 실행 } else if (job.status == 'success' && job.output is Map) { final url = (job.output as Map)['url']; print('Deployed: $url'); }

Embedded — Agent 운영

키오스크·전시 단말처럼 일반 앱 안에 Agent를 심는 시나리오예요.
첫 실행에서 enroll, 결과를 안전 저장소에 보관, 이후 부팅에선 그 자격으로 SSE를 구독해요.

import 'dart:async'; import 'package:deplite/deplite.dart'; Future<void> runAgent() async { final stored = await secureStore.loadAgent(); final agent = DepliteAgent( identity: stored.identity, privateKey: stored.privateKey, ); // 30초 heartbeat (기본값 일치) Timer.periodic(const Duration(seconds: 30), (_) async { try { await agent.heartbeat(); } catch (_) {} }); // 메인 이벤트 루프 await for (final event in agent.events()) { switch (event) { case DeployEvent(payload: final p): await _handleDeploy(agent, p); case SyncWorkflowsEvent(): await agent.workflows.report(_loadLocalWorkflows()); case RevokeEvent(): return; case PingEvent(): continue; case UnknownEvent(name: final n): print('unknown event: $n'); } } } Future<void> _handleDeploy(DepliteAgent agent, DeployPayload payload) async { try { await agent.jobs.appendLogs(jobId: payload.jobId, items: [ LogItem(seq: 0, stream: LogStream.system, level: LogLevel.info, content: 'started'), ]); final output = await runWorkflow(payload); await agent.jobs.reportResult( jobId: payload.jobId, result: JobResult.success(output: output), ); } catch (e) { await agent.jobs.reportResult( jobId: payload.jobId, result: JobResult.failed(exitCode: 1, errorMessage: '$e'), ); } }

secureStore는 예시명이에요.
실제로는 privateKey(raw 32바이트)는 암호화 후 저장하는 것을 추천드려요.

Embedded — 워크플로우 인벤토리 동기화

SyncWorkflowsEvent가 오면 현재 내가 실행 가능한 워크플로우 목록을 서버에 알려요.
실제 YAML 본문은 보내지 않고 이름과 메타만 보고해요.

Future<void> reportWorkflows(DepliteAgent agent) async { await agent.workflows.report([ const WorkflowReport( name: 'deploy-prod', verboseSteps: ['build', 'push'], secretsKeys: ['DB_URL'], ), const WorkflowReport(name: 'healthcheck', verboseSteps: ['ping']), ]); }

에러 처리 — 재시도 가능한 케이스만 백오프

Future<T> runWithRetry<T>(Future<T> Function() block, {int max = 3}) async { for (var i = 0; i < max; i++) { try { return await block(); } on DepliteAuthException { rethrow; // 재시도 무의미 } on DepliteApiException catch (e) { if (e.statusCode < 500 && e.statusCode != 429) rethrow; if (i == max - 1) rethrow; await Future.delayed(Duration(milliseconds: 500 * (1 << i))); } } throw StateError('unreachable'); }

관련 문서

최종 수정 일자: