API 레퍼런스
Deplite Swift SDK가 공개하는 모든 심볼을 시그니처와 함께 정리해요.
처음 보신다면 개요·Quickstart부터 읽어주세요.
진입 클래스
Deplite— External 모드 (Deplite를 호출)DepliteAgent— Embedded 모드 (내 앱이 작업 노드)
이 페이지의 모든 async throws 함수는 4xx/5xx 응답 시 DepliteError.api, 401·403 응답 시 DepliteError.unauthorized를 던질 수 있어요.
처리 방법은 예외 섹션을 참고해주세요.
class Deplite
public final class Deplite: @unchecked Sendable {
public static let defaultBaseURL: URL // https://api.deplite.io/v1
public let apiToken: String
public let baseURL: URL
public let triggers: Triggers
public let files: Files
public init(
apiToken: String,
baseURL: URL = Deplite.defaultBaseURL,
session: URLSession = .shared
)
}External 모드 클라이언트예요.
| 속성 | 타입 | 설명 |
|---|---|---|
apiToken | String | dpl_... 토큰 |
baseURL | URL | 기본 https://api.deplite.io/v1 |
triggers | Triggers | 트리거 호출 매니저 |
files | Files | External 파일 매니저 |
Deplite.enroll(…)
public static func enroll(
installCode: String,
name: String,
hostname: String? = nil,
os: String? = nil,
agentVersion: String? = nil,
baseURL: URL = Deplite.defaultBaseURL,
session: URLSession = .shared
) async throws -> EnrollmentEmbedded 모드용 1회 등록.
새 키쌍을 만들고 /agent/enroll을 호출해 Agent ID와 서버 공개키를 받아와요.
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
installCode | String | ✓ | 대시보드에서 발급한 1회용 설치 코드 (en_...) |
name | String | ✓ | 에이전트 표시 이름 |
hostname | String? | 호스트네임 | |
os | String? | "ios"·"macos" 등 | |
agentVersion | String? | 에이전트 버전 | |
baseURL | URL | API 베이스 오버라이드 |
결과는 Enrollment로 받아오며, 포함된 identity와 privateKey는 SDK가 보관하지 않으므로 호출 측이 암호화 후 저장하는 것을 추천드려요.
let enrollment = try await Deplite.enroll(
installCode: installCode,
name: "kiosk-seoul-01"
)
try secureStore.save(enrollment) // identity + privateKey설치 코드는 1회용이라 enroll 성공 후 폐기돼요.
저장 실패에 대비해 반환값을 먼저 저장한 뒤 후속 로직을 시작하는 게 안전해요.
struct Triggers
triggers.run(…)
public func run(
triggerId: String,
params: JSONValue? = nil,
workflowName: String? = nil,
ref: String? = nil,
debug: Bool = false,
idempotencyKey: String? = nil
) async throws -> TriggerRunResultPOST /triggers/{triggerId}/run을 호출해 트리거를 실행해요.
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
triggerId | String | ✓ | 트리거 UUID |
params | JSONValue? | 워크플로우에 전달될 페이로드 | |
workflowName | String? | agent-scope 트리거에서는 필수 | |
ref | String? | git ref | |
debug | Bool | verbose 실행 | |
idempotencyKey | String? | 중복 실행 방지 키 |
호출 결과는 TriggerRunResult로 받아요.
let job = try await deplite.triggers.run(
triggerId: triggerId,
params: ["ref": "main", "actor": "sehyun"],
idempotencyKey: "release-\(UUID().uuidString)"
)
print(job.jobId, job.status)responseMode: sync로 만들어진 트리거여야 응답에 exitCode·output이 와요.
async 트리거는 jobId만 즉시 반환되고, 결과는 알림이나 워크플로우 콜백으로 받아야 해요.
struct Files
External 모드에서 스토리지 파일을 다뤄요.
기본 CleanupRule은 .ttl(seconds: 86_400)(24시간)이에요.
files.upload(…)
public func upload(
fileURL: URL,
cleanupRule: CleanupRule = .ttl(seconds: 86_400),
filename: String? = nil,
contentType: String? = nil,
bindingId: String? = nil
) async throws -> FileMetapresign + PUT + complete를 하나의 호출로 처리해요.
| 옵션 | 타입 | 필수 | 설명 |
|---|---|---|---|
fileURL | URL | ✓ | 업로드할 로컬 파일 |
cleanupRule | CleanupRule | 기본 24h TTL | |
filename | String? | 미지정 시 파일명 자동 추론 | |
contentType | String? | MIME 타입 | |
bindingId | String? | 토큰이 여러 binding을 허용할 때 필수 |
업로드가 끝나면 FileMeta 객체로 활성화된 파일 정보를 돌려줘요.
let uploaded = try await deplite.files.upload(
fileURL: ipaURL,
cleanupRule: .ttl(seconds: 3600),
contentType: "application/octet-stream"
)
_ = try await deplite.triggers.run(
triggerId: triggerId,
params: ["ipaFileId": .string(uploaded.id), "ref": .string("main")]
)files.presignUpload(…)
public func presignUpload(
cleanupRule: CleanupRule,
filename: String? = nil,
contentType: String? = nil,
bindingId: String? = nil
) async throws -> PresignedUpload업로드 URL만 발급받아 직접 PUT 한 뒤 completeUpload를 호출하는 저수준 흐름이에요.
응답은 PresignedUpload로 받아오고, 이걸 가지고 직접 PUT 후 completeUpload를 호출하면 끝나요.
External 모드에서는 .onJobEnd를 쓸 수 없어요(잡 컨텍스트가 없으므로).
Agent Files 전용이에요.
files.completeUpload / downloadURL / download / get / list / delete
public func completeUpload(fileId: String) async throws -> FileMeta
public func downloadURL(fileId: String) async throws -> URL
@discardableResult
public func download(fileId: String, to destination: URL) async throws -> URL
public func get(fileId: String) async throws -> FileMeta
public func list(bindingId: String? = nil, status: String? = nil) async throws -> [FileMeta]
public func delete(fileId: String) async throwscompleteUpload는 PUT을 마친 뒤 파일을 활성 상태로 만들어요.
downloadURL은 짧은 만료의 다운로드 URL을 발급하므로, 다운로드 직전에 새로 받는 게 안전해요.
download는 destination에 직접 저장하며 반환은 그 URL 그대로예요.
list는 토큰이 접근 가능한 binding 내 파일만 보여줘요.
class DepliteAgent
public final class DepliteAgent: @unchecked Sendable {
public let identity: AgentIdentity
public let workflows: AgentWorkflows
public let jobs: AgentJobs
public let files: AgentFiles
public init(
identity: AgentIdentity,
privateKey: Data, // 정확히 32바이트
session: URLSession = .shared
) throws
}Embedded 모드 클라이언트예요.
enroll() 결과를 별도 저장소에서 꺼내 넘기면 돼요.
| 속성 | 타입 | 설명 |
|---|---|---|
identity | AgentIdentity | 등록 시 받은 비밀이 아닌 신원 |
workflows | AgentWorkflows | 워크플로우 인벤토리 보고 |
jobs | AgentJobs | Job 로그·결과 보고 |
files | AgentFiles | Job 범위 파일 매니저 |
생성자에 전달된 privateKey가 32바이트가 아니면 즉시 DepliteError.invalidPrivateKey가 던져져요.
agent.heartbeat()
public func heartbeat() async throws서명된 heartbeat를 1회 송신해요(추천 주기 30초).
agent.updateIdentity(…)
public func updateIdentity(
hostname: String? = nil,
os: String? = nil,
agentVersion: String? = nil
) async throws호스트네임·OS·버전 변경 시 PATCH로 알려요.
agent.events()
public func events() -> AsyncThrowingStream<AgentEvent, Error>SSE 스트림을 AsyncThrowingStream으로 노출해요.
서버 → Agent 명령(deploy 등)의 서명 검증은 SDK가 자동 처리하므로 호출 측은 이벤트 타입만 분기하면 돼요.
이벤트 종류는 AgentEvent를 참고해주세요.
for try await event in agent.events() {
switch event {
case .deploy(let payload, _):
try await handleDeploy(payload)
case .syncWorkflows:
_ = try await agent.workflows.report(loadLocal())
case .revoke:
return
case .ping:
continue
case .unknown(let name, _):
print("unknown:", name)
}
}전체 시나리오는 예제 페이지에 있어요.
struct AgentJobs
jobs.appendLogs(…)
@discardableResult
public func appendLogs(jobId: String, items: [LogItem]) async throws -> IntLogItem 배열을 한 번에 보내요.
서버가 실제로 수락한 라인 수가 돌아오고, 추천 배치 크기는 64KB 또는 1초 간격 중 빠른 쪽이에요.
jobs.reportResult(…)
public func reportResult(jobId: String, result: JobResult) async throws잡당 1회만 호출해요.
JobResult는 직접 만들기보다 팩토리(JobResult.success 등)를 추천드려요.
do {
let output = try await runWorkflow(payload)
try await agent.jobs.reportResult(
jobId: payload.jobId,
result: .success(output: output)
)
} catch {
try await agent.jobs.reportResult(
jobId: payload.jobId,
result: .failed(exitCode: 1, errorMessage: "\(error)")
)
}struct AgentFiles
Job 컨텍스트 안에서 산출물 파일을 다뤄요.
기본 CleanupRule은 .onJobEnd라 잡 종료 시 자동 정리돼요.
각 메소드의 옵션과 반환값은 External Files와 동일하고, 모든 호출에 jobId가 추가로 필요한 점만 달라요.
public func upload(jobId: String, fileURL: URL, ...) async throws -> FileMeta
public func presignUpload(jobId: String, ...) async throws -> PresignedUpload
public func complete(fileId: String) async throws -> FileMeta
public func downloadURL(fileId: String) async throws -> URL
public func download(fileId: String, to: URL) async throws -> URL
public func get(fileId: String) async throws -> FileMeta
public func delete(fileId: String) async throwsExternal의 Files와 달리 모든 호출이 서명되고 jobId로 스코프돼요.
list는 노출되지 않아요.
struct AgentWorkflows
workflows.report(…)
@discardableResult
public func report(_ workflows: [WorkflowReport]) async throws -> Int서버에 알려진 워크플로우 인벤토리를 WorkflowReport 배열로 완전히 교체해요.
보고된 워크플로우 수가 돌아와요.
실제 YAML·step run 명령·시크릿 값은 보내지 않는 것을 추천드려요.
이름·메타만 보고하는 게 격리 모델의 핵심이에요.
타입 참조
Enrollment
public struct Enrollment: Sendable, Equatable {
public let identity: AgentIdentity
public let privateKey: Data // raw 32-byte 개인키
}Deplite.enroll의 결과. 두 필드 모두 호출 측이 암호화 후 저장하는 것을 추천드려요.
AgentIdentity
public struct AgentIdentity: Codable, Sendable, Equatable {
public let agentId: String
public let organizationId: String
public let baseURL: URL
public let serverPublicKeyPEM: String
}비밀이 아니라 일반 저장소에 두어도 무방해요.
AgentEvent
public enum AgentEvent: Sendable {
case deploy(payload: DeployPayload, signature: String)
case revoke
case syncWorkflows
case ping
case unknown(name: String, data: String)
}| 케이스 | 의미 |
|---|---|
.deploy | 워크플로우 실행 명령 (payload에 jobId·workflowName·params 등) |
.revoke | Agent 자격 회수 |
.syncWorkflows | 워크플로우 인벤토리 재보고 요청 |
.ping | keep-alive |
.unknown | 알 수 없는 이벤트 또는 서명 검증 실패 |
DeployPayload
public struct DeployPayload: Sendable, Equatable, Decodable {
public let jobId: String
public let workflowName: String
public let debug: Bool
public let ref: String?
public let params: JSONValue?
public let issuedAt: Int64
public let nonce: String
public let force: Bool
public let forceReason: String?
}TriggerRunResult
public struct TriggerRunResult: Decodable, Sendable, Equatable {
public let jobId: String
public let status: String
public let idempotent: Bool
public let timedOut: Bool
public let exitCode: Int?
public let errorMessage: String?
public let output: JSONValue?
public let statusUrl: URL?
}CleanupRule
public enum CleanupRule: Sendable, Equatable {
case ttl(seconds: Int64) // 60s ≤ seconds ≤ 90일
case persistent
case onJobEnd // Agent Files 전용
}FileMeta
public struct FileMeta: Decodable, Sendable, Equatable {
public let id: String
public let bindingId: String?
public let jobId: String?
public let filename: String?
public let contentType: String?
public let size: Int64?
public let status: String?
public let cleanupRule: String?
public let expiresAt: String?
public let createdAt: String?
}PresignedUpload
public struct PresignedUpload: Decodable, Sendable, Equatable {
public let fileId: String
public let uploadUrl: URL
public let uploadHeaders: [String: String]?
public let expiresInSeconds: Int?
}LogItem
public enum LogStream: String, Codable, Sendable { case raw, system }
public enum LogLevel: String, Codable, Sendable { case info, warn, error }
public struct LogItem: Sendable, Equatable {
public let seq: Int
public let stream: LogStream
public let content: String
public let stepName: String?
public let level: LogLevel?
}JobResult
public enum JobStatus: String, Codable, Sendable {
case running, success, failed, timeout, rejected
}
public struct JobResult: Sendable, Equatable {
public let status: JobStatus
public let exitCode: Int?
public let errorMessage: String?
public let output: JSONValue?
public let rejection: Rejection?
public struct Rejection: Sendable, Equatable {
public let reason: String
public let limitType: String?
public let retryAfterSeconds: Int?
public let bypassedLimits: [String]
}
public static func running() -> JobResult
public static func success(exitCode: Int = 0, output: JSONValue? = nil) -> JobResult
public static func failed(exitCode: Int? = nil, errorMessage: String? = nil) -> JobResult
public static func timeout(errorMessage: String? = nil) -> JobResult
public static func rejected(_ rejection: Rejection) -> JobResult
}직접 만들기보다 success·failed 같은 팩토리 사용을 추천드려요.
WorkflowReport
public struct WorkflowReport: Codable, Sendable, Equatable {
public let name: String
public let verboseSteps: [String]
public let secretsKeys: [String]
}JSONValue
public enum JSONValue: Codable, Sendable, Equatable {
case null
case bool(Bool)
case int(Int64)
case double(Double)
case string(String)
case array([JSONValue])
case object([String: JSONValue])
}리터럴 초기화 지원: let v: JSONValue = ["ref": "main", "count": 3]처럼 직접 작성 가능해요.
예외
DepliteError
public enum DepliteError: Error, Sendable {
case api(statusCode: Int, body: String)
case unauthorized(statusCode: Int, body: String)
case transport(underlying: Error)
case decoding(underlying: Error, body: String)
case invalidPrivateKey
case signing(reason: String)
case sseClosed(reason: String)
}| 케이스 | 발생 |
|---|---|
.api(statusCode, body) | 4xx·5xx (401·403 제외) |
.unauthorized | 401·403 — Embedded는 재등록이 필요해요 |
.transport | 네트워크·URLSession 오류 |
.decoding | 응답 JSON 파싱 실패 |
.invalidPrivateKey | 32바이트 아닌 키로 DepliteAgent 생성 |
.signing | 서명 자체 실패 |
.sseClosed | SSE 스트림 비정상 종료 |
추천 처리 패턴
do {
_ = try await deplite.triggers.run(triggerId: triggerId)
} catch DepliteError.unauthorized {
// 토큰 회수·교체 필요
} catch let DepliteError.api(status, _) where status == 429 || status >= 500 {
// 백오프 후 재시도
} catch let DepliteError.api(_, _) {
// 4xx 클라이언트 오류
} catch {
// 네트워크·기타
}