Files
dify/cli/scripts/install-cli.test.ts
GareArc d84fad76ed feat(cli): trigger-agnostic difyctl release pipeline + tokenless installers
- cli-release.yml: workflow_dispatch/workflow_call/repository_dispatch/tag
  triggers; version sourced from cli/package.json (not the trigger). Split into
  validate + release jobs with an idempotency guard (gh release view) and a
  tag-vs-manifest match guard so a difyctl-v* tag push must equal the manifest
  version (prevents a dangling/mismatched tag). Releases may be cut from any
  branch. Concurrency serialized (fixed group, cancel-in-progress: false) so
  releases never double-publish.
- install-cli.sh: tokenless resolution via git/matching-refs, channel-aware
  (stable/rc) selection, fail-closed sha256 verification; distinguishes a fetch
  failure (network / API rate limit) from "no release found".
- install.ps1: Windows installer at parity with install-cli.sh.
- install-cli.test.ts: resolver unit tests (rc ordering, channel filter).
- .bun-version: pin Bun 1.3.11 for reproducible --compile builds.
2026-06-03 19:23:55 -07:00

51 lines
1.8 KiB
TypeScript

import { execFileSync } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
const SCRIPT = fileURLToPath(new URL('./install-cli.sh', import.meta.url))
// Drive the pure resolver: `. install-cli.sh; select_version <channel>` with
// the matching-refs JSON piped to stdin. DIFYCTL_INSTALL_LIB=1 stops main running.
function selectVersion(channel: string, refsJson: string): string {
return execFileSync('sh', ['-c', `. "${SCRIPT}"; select_version "$1"`, 'sh', channel], {
input: refsJson,
encoding: 'utf8',
env: { ...process.env, DIFYCTL_INSTALL_LIB: '1' },
}).trim()
}
// A git/matching-refs/tags/difyctl-v response in arbitrary (non-sorted) order,
// with a stray non-difyctl ref to prove the filter is strict.
const REFS = JSON.stringify([
{ ref: 'refs/tags/difyctl-v0.1.0-rc.1' },
{ ref: 'refs/tags/difyctl-v0.2.0' },
{ ref: 'refs/tags/difyctl-v0.1.0' },
{ ref: 'refs/tags/some-other-tag' },
{ ref: 'refs/tags/difyctl-v0.2.0-rc.2' },
{ ref: 'refs/tags/difyctl-v0.10.0' },
{ ref: 'refs/tags/difyctl-v0.2.0-rc.10' },
])
describe('install-cli select_version', () => {
it('stable picks the highest non-prerelease difyctl version', () => {
expect(selectVersion('stable', REFS)).toBe('0.10.0')
})
it('rc picks the highest rc (semver-aware: rc.10 > rc.2)', () => {
expect(selectVersion('rc', REFS)).toBe('0.2.0-rc.10')
})
it('ignores non-difyctl refs entirely', () => {
const noisy = JSON.stringify([{ ref: 'refs/tags/v1.15.0' }, { ref: 'refs/tags/difyctl-v0.3.0' }])
expect(selectVersion('stable', noisy)).toBe('0.3.0')
})
it('yields empty when there are no difyctl tags', () => {
expect(selectVersion('stable', '[]')).toBe('')
})
it('rejects an invalid channel', () => {
expect(() => selectVersion('nightly', REFS)).toThrow()
})
})