/**
* DeployConfig — Per-repo deploy configuration stored in Hyperbee
*
* Config fields per repo:
* enabled: boolean
* channel: string (target channel/branch)
* mode: 'git' | 'legacy'
* autoRelease: boolean
* autoSeed: boolean
* autoDeploy: boolean (trigger deploy on push)
* configuredAt: timestamp
*/
export class DeployConfig {
constructor (bee) {
this._bee = bee
}
async get (repoName) {
const entry = await this._bee.get(`deploy-config:${repoName}`)
return entry ? entry.value : null
}
async set (repoName, config) {
const existing = await this.get(repoName) || {}
const merged = {
...existing,
...config,
repoName,
configuredAt: Date.now()
}
await this._bee.put(`deploy-config:${repoName}`, merged)
return merged
}
async delete (repoName) {
await this._bee.del(`deploy-config:${repoName}`)
}
async list () {
const configs = []
for await (const entry of this._bee.createReadStream({
gt: 'deploy-config:', lt: 'deploy-config:\xff'
})) {
configs.push(entry.value)
}
return configs
}
async isEnabled (repoName) {
const config = await this.get(repoName)
return config ? config.enabled === true : false
}
async shouldAutoDeploy (repoName) {
const config = await this.get(repoName)
return config ? config.autoDeploy === true : false
}
}
/**
* DeployLog — Deploy history per repo stored in Hyperbee
*
* Each entry: { timestamp, status, commitHash, duration, error?, message? }
*/
export class DeployLog {
constructor (bee) {
this._bee = bee
}
async append (repoName, entry) {
const key = `deploy-log:${repoName}:${Date.now()}`
await this._bee.put(key, {
...entry,
repoName,
timestamp: Date.now()
})
}
async getLog (repoName, limit = 20) {
const entries = []
for await (const entry of this._bee.createReadStream({
gt: `deploy-log:${repoName}:`, lt: `deploy-log:${repoName}:\xff`,
reverse: true, limit
})) {
entries.push(entry.value)
}
return entries
}
async getLatest (repoName) {
for await (const entry of this._bee.createReadStream({
gt: `deploy-log:${repoName}:`, lt: `deploy-log:${repoName}:\xff`,
reverse: true, limit: 1
})) {
return entry.value
}
return null
}
async clear (repoName) {
const keys = []
for await (const entry of this._bee.createReadStream({
gt: `deploy-log:${repoName}:`, lt: `deploy-log:${repoName}:\xff`
})) {
keys.push(entry.key)
}
for (const key of keys) await this._bee.del(key)
}
}
/**
* getDeployStatus — assemble status from config + log
*/
export async function getDeployStatus (config, log, repoName) {
const cfg = await config.get(repoName)
const latest = await log.getLatest(repoName)
return {
repoName,
configured: !!cfg,
enabled: cfg?.enabled || false,
mode: cfg?.mode || 'git',
channel: cfg?.channel || 'release',
autoDeploy: cfg?.autoDeploy || false,
autoRelease: cfg?.autoRelease || false,
autoSeed: cfg?.autoSeed || false,
lastDeploy: latest ? {
timestamp: latest.timestamp,
status: latest.status,
commitHash: latest.commitHash,
duration: latest.duration,
error: latest.error || null
} : null
}
}