OverviewFilesCommitsIssuesDocsReleasesPeers

pgh-sidecar / test / autoupdate-staged.test.js

54 lines · javascript ref:
/**
 * Autoupdate does not re-install a version pgh already STAGED.
 *
 * pgh never swaps a running app's tree: an install that finds the app running
 * leaves the new tree as <name>.next, applied at the app's next launch (pgh
 * lib/materializers/atomic.js). The live manifest still says the old version,
 * so after a sidecar restart (empty _lastNotifiedVersion) every update tick
 * would rebuild and re-stage the same tree. The staged manifest's version is
 * the tie-breaker.
 */
import test from 'brittle'
import { Sidecar } from '../lib/index.js'

function stub (cand) {
  const s = Object.create(Sidecar.prototype)
  s._installFailures = new Map()
  s._installInFlight = new Set()
  s._lastNotifiedVersion = new Map()
  s._releaseReplicas = []
  s._registry = { latest: async () => ({ version: '2', treeHash: 't2', publishedAt: 1 }) }
  s._listUpdateCandidates = async () => [cand]
  s._isAutoupdateEnabled = () => true
  s._reconcileBootstrap = async () => {}
  s.installs = []
  s._installRelease = async (name, best) => { s.installs.push(name + '@' + best.version) }
  return s
}

test('a release already staged for the running app is not installed again', async (t) => {
  const s = stub({ name: 'app', currentVersion: '1', currentTreeHash: 't1', stagedVersion: '2', registered: false })
  await s._notifyAppsOfNewReleases()
  t.alike(s.installs, [], 'no install: version 2 is already staged')
})

test('a newer release than the staged one is installed', async (t) => {
  const s = stub({ name: 'app', currentVersion: '1', currentTreeHash: 't1', stagedVersion: '1.5', registered: false })
  await s._notifyAppsOfNewReleases()
  t.alike(s.installs, ['app@2'])
})

test('nothing staged: installed as before', async (t) => {
  const s = stub({ name: 'app', currentVersion: '1', currentTreeHash: 't1', stagedVersion: null, registered: false })
  await s._notifyAppsOfNewReleases()
  t.alike(s.installs, ['app@2'])
})

test('_stagedVersion reads <name>.next\'s manifest', (t) => {
  const s = Object.create(Sidecar.prototype)
  const read = (n) => (n === 'app.next' ? { version: '2' } : null)
  t.is(s._stagedVersion('app', read), '2')
  t.is(s._stagedVersion('other', read), null)
  t.is(s._stagedVersion('app', null), null)
})