Compare commits

..

1 Commits

Author SHA1 Message Date
Connor Byrne
f831701040 fix: publish core/* releases immediately to create tags
Draft releases don't create git tags, but publish-pypi workflow
waits for the tag to exist. This caused core/* releases to hang
indefinitely since they were always drafts.

Change: only use draft for prereleases (alpha/beta/rc), publish
all stable releases (main and core/*) immediately.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-06-18 22:46:39 -07:00
3 changed files with 3 additions and 170 deletions

View File

@@ -92,9 +92,7 @@ jobs:
make_latest: >-
${{ github.event.pull_request.base.ref == 'main' &&
needs.build.outputs.is_prerelease == 'false' }}
draft: >-
${{ github.event.pull_request.base.ref != 'main' ||
needs.build.outputs.is_prerelease == 'true' }}
draft: ${{ needs.build.outputs.is_prerelease == 'true' }}
prerelease: >-
${{ needs.build.outputs.is_prerelease == 'true' }}
generate_release_notes: true

View File

@@ -1,165 +0,0 @@
import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createI18n } from 'vue-i18n'
import type { CreateTopupResponse } from '@/platform/workspace/api/workspaceApi'
import TopUpCreditsDialogContentWorkspace from './TopUpCreditsDialogContentWorkspace.vue'
const mockFetchBalance = vi.fn()
const mockFetchStatus = vi.fn()
const mockTopup = vi.fn<(amountCents: number) => Promise<CreateTopupResponse>>()
const mockStartOperation = vi.fn()
const mockShowSettings = vi.fn()
const mockToastAdd = vi.fn()
vi.mock('@/composables/billing/useBillingContext', () => ({
useBillingContext: () => ({
fetchBalance: mockFetchBalance,
fetchStatus: mockFetchStatus,
topup: (amountCents: number) => mockTopup(amountCents)
})
}))
vi.mock('@/platform/workspace/stores/billingOperationStore', () => ({
useBillingOperationStore: () => ({
hasPendingOperations: false,
startOperation: mockStartOperation
})
}))
vi.mock('@/platform/settings/composables/useSettingsDialog', () => ({
useSettingsDialog: () => ({ show: mockShowSettings })
}))
vi.mock('@/stores/dialogStore', () => ({
useDialogStore: () => ({ closeDialog: vi.fn() })
}))
vi.mock('@/platform/telemetry', () => ({
useTelemetry: () => ({
trackApiCreditTopupButtonPurchaseClicked: vi.fn()
})
}))
vi.mock('@/platform/telemetry/topupTracker', () => ({
clearTopupTracking: vi.fn()
}))
vi.mock('@/composables/useExternalLink', () => ({
useExternalLink: () => ({
buildDocsUrl: () => 'https://docs.comfy.org',
docsPaths: { partnerNodesPricing: '' }
})
}))
vi.mock('primevue/usetoast', () => ({
useToast: () => ({ add: mockToastAdd })
}))
vi.mock('@/base/credits/comfyCredits', () => ({
creditsToUsd: (credits: number) => credits,
usdToCredits: (usd: number) => usd
}))
const i18n = createI18n({
legacy: false,
locale: 'en',
messages: {
en: {
g: { close: 'Close' },
subscription: { addCredits: 'Add credits' },
credits: {
topUp: {
addMoreCredits: 'Add more credits',
addMoreCreditsToRun: 'Add more credits to run',
selectAmount: 'Select amount',
youPay: 'You pay',
youGet: 'You get',
purchaseSuccess: 'Credits added successfully!',
purchaseError: 'Purchase Failed',
purchaseErrorDetail: 'Failed to purchase credits: {error}',
unknownError: 'An unknown error occurred',
minRequired: 'Minimum required',
maxAllowed: 'Maximum allowed',
needMore: 'Need more?',
contactUs: 'Contact us',
viewPricing: 'View pricing',
insufficientWorkflowMessage: 'Insufficient credits'
}
}
}
}
})
function topupResponse(
status: CreateTopupResponse['status']
): CreateTopupResponse {
return {
billing_op_id: 'op-1',
topup_id: 'topup-1',
status,
amount_cents: 5000
}
}
function renderDialog() {
return render(TopUpCreditsDialogContentWorkspace, {
global: {
plugins: [i18n],
stubs: {
FormattedNumberStepper: {
name: 'FormattedNumberStepper',
props: ['modelValue'],
template: '<div />'
}
}
}
})
}
async function clickAddCredits() {
const user = userEvent.setup()
await user.click(screen.getByRole('button', { name: 'Add credits' }))
}
describe('TopUpCreditsDialogContentWorkspace', () => {
beforeEach(() => {
vi.clearAllMocks()
mockFetchBalance.mockResolvedValue(undefined)
mockFetchStatus.mockResolvedValue(undefined)
})
it('refreshes both balance and status after a completed top-up', async () => {
mockTopup.mockResolvedValue(topupResponse('completed'))
renderDialog()
await clickAddCredits()
expect(mockFetchBalance).toHaveBeenCalledOnce()
expect(mockFetchStatus).toHaveBeenCalledOnce()
expect(mockShowSettings).toHaveBeenCalledWith('workspace')
})
it('does not refresh balance or status for a pending top-up', async () => {
mockTopup.mockResolvedValue(topupResponse('pending'))
renderDialog()
await clickAddCredits()
expect(mockStartOperation).toHaveBeenCalledWith('op-1', 'topup')
expect(mockFetchBalance).not.toHaveBeenCalled()
expect(mockFetchStatus).not.toHaveBeenCalled()
})
it('does not refresh balance or status for a failed top-up', async () => {
mockTopup.mockResolvedValue(topupResponse('failed'))
renderDialog()
await clickAddCredits()
expect(mockFetchBalance).not.toHaveBeenCalled()
expect(mockFetchStatus).not.toHaveBeenCalled()
})
})

View File

@@ -176,7 +176,7 @@ const settingsDialog = useSettingsDialog()
const telemetry = useTelemetry()
const toast = useToast()
const { buildDocsUrl, docsPaths } = useExternalLink()
const { fetchBalance, fetchStatus, topup } = useBillingContext()
const { fetchBalance, topup } = useBillingContext()
const billingOperationStore = useBillingOperationStore()
const isPolling = computed(() => billingOperationStore.hasPendingOperations)
@@ -265,7 +265,7 @@ async function handleBuy() {
summary: t('credits.topUp.purchaseSuccess'),
life: 5000
})
await Promise.all([fetchBalance(), fetchStatus()])
await fetchBalance()
handleClose(false)
settingsDialog.show('workspace')
} else if (response.status === 'pending') {