feat(cli): prepare for alpha release (#37794)

This commit is contained in:
Xiyuan Chen 2026-06-23 01:07:15 -07:00 committed by GitHub
parent f4fdbeba76
commit d764b16d06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 69 additions and 34 deletions

View File

@ -1,12 +1,12 @@
{
"name": "@langgenius/difyctl",
"type": "module",
"version": "0.1.0-rc.1",
"version": "0.1.0-alpha",
"description": "Dify command-line interface",
"difyctl": {
"channel": "rc",
"channel": "alpha",
"compat": {
"minDify": "1.14.0",
"minDify": "1.15.0",
"maxDify": "1.15.0"
},
"release": {

View File

@ -4,7 +4,7 @@ import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
export const BUILD_CHANNELS = ['dev', 'rc', 'stable'] as const
export const BUILD_CHANNELS = ['dev', 'alpha', 'rc', 'edge', 'stable'] as const
export type BuildChannel = (typeof BUILD_CHANNELS)[number]
export type BuildInfo = {

View File

@ -26,6 +26,7 @@ const SEMVER_CORE_LEN = 3
// Add channels here: { name, prerelease, versionForm }.
const CHANNELS = [
{ name: 'stable', prerelease: false, versionForm: /^\d+\.\d+\.\d+(\+[0-9A-Z.-]+)?$/i },
{ name: 'alpha', prerelease: true, versionForm: /^\d+\.\d+\.\d+-alpha(\.\d+)?$/ },
{ name: 'rc', prerelease: true, versionForm: /^\d+\.\d+\.\d+-rc\.\d+$/ },
{ name: 'edge', prerelease: true, versionForm: /^\d+\.\d+\.\d+-edge\.[0-9a-f]{7,40}$/ },
]

View File

@ -15,13 +15,13 @@ function run(args: string[]): { code: number, stdout: string, stderr: string } {
}
}
describe('release-naming compat-check (compat 1.14.0..1.15.0)', () => {
describe('release-naming compat-check (compat 1.15.0..1.15.0)', () => {
it('accepts a version inside the window', () => {
expect(run(['compat-check', '1.14.7']).code).toBe(0)
expect(run(['compat-check', '1.15.0']).code).toBe(0)
})
it('accepts the inclusive lower bound', () => {
expect(run(['compat-check', '1.14.0']).code).toBe(0)
expect(run(['compat-check', '1.15.0']).code).toBe(0)
})
it('accepts the inclusive upper bound', () => {
@ -29,26 +29,22 @@ describe('release-naming compat-check (compat 1.14.0..1.15.0)', () => {
})
it('accepts a v-prefixed tag', () => {
expect(run(['compat-check', 'v1.14.2']).code).toBe(0)
expect(run(['compat-check', 'v1.15.0']).code).toBe(0)
})
it('rejects a version below the lower bound', () => {
expect(run(['compat-check', '1.13.9']).code).not.toBe(0)
expect(run(['compat-check', '1.14.9']).code).not.toBe(0)
})
it('rejects a version above the upper bound', () => {
expect(run(['compat-check', '1.15.1']).code).not.toBe(0)
})
it('treats a prerelease of the upper bound as in range (1.15.0-rc1 <= 1.15.0)', () => {
expect(run(['compat-check', '1.15.0-rc1']).code).toBe(0)
it('treats a prerelease of the bound as below it (1.15.0-rc1 < 1.15.0)', () => {
expect(run(['compat-check', '1.15.0-rc1']).code).not.toBe(0)
})
it('treats a prerelease of the lower bound as below it (1.14.0-rc1 < 1.14.0)', () => {
expect(run(['compat-check', '1.14.0-rc1']).code).not.toBe(0)
})
it('ignores build metadata on the upper bound (1.15.0+build == 1.15.0)', () => {
it('ignores build metadata on the bound (1.15.0+build == 1.15.0)', () => {
expect(run(['compat-check', '1.15.0+build123']).code).toBe(0)
})
@ -64,7 +60,7 @@ describe('release-naming compat-check (compat 1.14.0..1.15.0)', () => {
describe('release-naming github-env', () => {
it('emits difyctlTag = tagPrefix + version', () => {
const { stdout } = run(['github-env'])
expect(stdout).toMatch(/^difyctlTag=difyctl-v0\.1\.0-rc\.1$/m)
expect(stdout).toMatch(/^difyctlTag=difyctl-v0\.1\.0-alpha$/m)
})
it('still emits the existing trace fields', () => {
@ -79,8 +75,8 @@ describe('release-naming edge channel', () => {
expect(run(['channels']).stdout).toMatch(/^edge$/m)
})
it('edge-version derives <pkgcore>-edge.<sha> stripping the rc prerelease', () => {
// package.json version is 0.1.0-rc.1 -> core 0.1.0
it('edge-version derives <pkgcore>-edge.<sha> stripping the alpha prerelease', () => {
// package.json version is 0.1.0-alpha -> core 0.1.0
expect(run(['edge-version', '2fd7b82']).stdout.trim()).toBe('0.1.0-edge.2fd7b82')
})

View File

@ -81,7 +81,7 @@ describe('release-r2-edge manifest', () => {
it('carries the compat window from package.json', () => {
const { json } = buildManifest()
expect(json.compat).toEqual({ minDify: '1.14.0', maxDify: '1.15.0' })
expect(json.compat).toEqual({ minDify: '1.15.0', maxDify: '1.15.0' })
})
it('lists all 5 targets with asset name + sha256 from the checksums file', () => {

View File

@ -158,6 +158,6 @@ describe('Version command', () => {
if (output?.kind !== 'formatted')
throw new Error('expected formatted output')
expect(output.data.text()).toContain('WARNING: This build is a release candidate')
expect(output.data.text()).toContain('WARNING: This build is a rc release')
})
})

View File

@ -1,7 +1,7 @@
import { arch, platform } from '@/sys/index'
import { compatString } from './compat'
export type Channel = 'dev' | 'edge' | 'rc' | 'stable'
export type Channel = 'dev' | 'alpha' | 'edge' | 'rc' | 'stable'
export type VersionInfo = {
version: string

View File

@ -52,7 +52,7 @@ describe('renderVersionText', () => {
expect(text).not.toContain('WARNING:')
})
it('appends RC warning when channel is rc', () => {
it('appends warning when channel is rc', () => {
const report: VersionReport = {
client: baseClient({ channel: 'rc' }),
server: { endpoint: '', reachable: false },
@ -60,8 +60,43 @@ describe('renderVersionText', () => {
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a release candidate')
expect(text).toContain('install the stable channel')
expect(text).toContain('WARNING: This build is a rc release')
expect(text).toContain('install or wait for the stable channel')
})
it('appends warning when channel is alpha', () => {
const report: VersionReport = {
client: baseClient({ channel: 'alpha' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a alpha release')
expect(text).toContain('install or wait for the stable channel')
})
it('appends warning when channel is edge', () => {
const report: VersionReport = {
client: baseClient({ channel: 'edge' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).toContain('WARNING: This build is a edge release')
expect(text).toContain('install or wait for the stable channel')
})
it('does not append warning when channel is stable', () => {
const report: VersionReport = {
client: baseClient({ channel: 'stable' }),
server: { endpoint: '', reachable: false },
compat: { ...compatible(), status: 'unknown', detail: 'server probe skipped' },
}
const text = renderVersionText(report)
expect(text).not.toContain('WARNING:')
})
it('shows "(skipped …)" when server.endpoint is empty', () => {
@ -105,7 +140,7 @@ describe('renderVersionText', () => {
// RC warning) ran, yet the output is byte-clean.
expect(plain).not.toMatch(ANSI_RE)
expect(plain).toContain('Compatibility: incompatible')
expect(plain).toContain('WARNING: This build is a release candidate')
expect(plain).toContain('WARNING: This build is a rc release')
})
describe('with picocolors stubbed to always emit ANSI', () => {
@ -147,8 +182,8 @@ describe('renderVersionText', () => {
const colored = render(report, { color: true })
expect(colored).toMatch(ANSI_RE)
expect(colored).toContain('Compatibility: incompatible')
// RC warning lines also routed through yellow.
expect(colored).toContain('release candidate')
// prerelease warning lines also routed through yellow.
expect(colored).toContain('WARNING: This build is a rc release')
})
})

View File

@ -1,10 +1,13 @@
import type { Channel } from './info'
import type { VersionReport } from './probe'
import { colorScheme } from '@/sys/io/color'
const RC_WARNING_LINES = [
'WARNING: This build is a release candidate. It is in beta test, not stable,',
' and may have bugs. For production use, install the stable channel.',
] as const
function prereleaseWarning(channel: Channel): readonly string[] {
return [
`WARNING: This build is a ${channel} release. It is not stable`,
' and may have bugs. For production use, install or wait for the stable channel.',
]
}
export type RenderOptions = {
readonly color?: boolean
@ -49,9 +52,9 @@ export function renderVersionText(report: VersionReport, opts: RenderOptions = {
const verdictText = `Compatibility: ${COMPAT_LABEL[compat.status]}${compat.detail}`
lines.push(compat.status === 'unsupported' ? c.yellow(verdictText) : verdictText)
if (client.channel === 'rc') {
if (client.channel !== 'stable') {
lines.push('')
for (const line of RC_WARNING_LINES)
for (const line of prereleaseWarning(client.channel))
lines.push(c.yellow(line))
}