{#if $workspaceStore != currentWorkspaceId} You are currently seeing the deployement page of workspace {currentWorkspaceInfo?.name} ({currentWorkspaceInfo?.id}) which is not your currently selected workspace. Click here to go home ({$workspaceStore}) {/if} {#if comparisonError && !comparison}
{comparisonError}
{#if onRetry} {/if} {#if onSelectTarget} {/if}
{:else if comparison} {@const selectedConflicts = conflictingDiffs.filter((e) => selectedItems.includes(getItemKey(e)) ).length}
removesInTarget(item.diff as WorkspaceItemDiff)} onToggleItem={(item) => toggleKey(item.key)} onSelectAll={selectAll} onDeselectAll={deselectAll} emptyMessage={emptyDeployMessage} > {#snippet header()}
{#if currentWorkspaceInfo && parentWorkspaceInfo}
merge: {#if mergeIntoParent} {currentWorkspaceInfo.id} {:else} {parentWorkspaceInfo.id} {/if} {#if mergeIntoParent && onSelectTarget} {#snippet triggerContent()} into: {parentWorkspaceInfo.id} {/snippet} {:else} into: {#if !mergeIntoParent} {currentWorkspaceInfo.id} {:else} {parentWorkspaceInfo.id} {/if} {/if}
{/if}
{selectableDiffs.length} {mergeIntoParent ? 'deployable' : 'updateable'} {#if conflictingDiffs.length > 0} {conflictingDiffs.length} conflicts {/if}
{#if isArbitraryTarget && fullScanAt}
Diff computed {displayDate(fullScanAt)}
{/if}
{/snippet} {#snippet groupActions(groupItems)} {@const groupConflicts = groupItems.filter((i) => { const d = i.diff as WorkspaceItemDiff return d.ahead > 0 && d.behind > 0 }).length} {#if groupConflicts > 0} {groupConflicts} conflict{groupConflicts !== 1 ? 's' : ''} {/if} {/snippet} {#if allCiTests.length > 0}
CI tests
{#each allCiTests as test (test.test_script_path)}
{#if test.status === 'success'} {:else if test.status === 'failure' || test.status === 'canceled'} {:else if test.status === 'running'} {:else}
{/if} {test.test_script_path} {#if test.job_id} view run {/if}
{/each}
{/if} {#snippet alerts()} {#if comparisonError}
{comparisonError} {#if onRetry} {/if}
{:else if awaitingScan}
{parentWorkspaceId} is not in this workspace's lineage, so their differences aren't tracked as you deploy. Computing the diff compares every item on both sides — it can take a while on large workspaces, and the result is kept for later visits.
{/if} {#if isArbitraryTarget && !awaitingScan} Items are compared as of the last scan, and can only be sent from this workspace into {parentWorkspaceId}. Anything created or changed on either side since is missing from the list until you recompute. {/if} {#if draftCount > 0}
{#if mergeIntoParent} This workspace has {draftCount} undeployed draft{draftCount !== 1 ? 's' : ''}. Only deployed versions in this {currentNoun} can be sent to {parentWorkspaceId} — deploy {draftCount !== 1 ? 'them' : 'it'} first, otherwise those changes won't be included. {:else} This workspace has {draftCount} undeployed draft{draftCount !== 1 ? 's' : ''}. {/if}
{/if} {#if mergeIntoParent} { canDeployToParent = canDeploy }} /> {/if} {#if conflictingDiffs.length > 0} {conflictingDiffs.length} item{conflictingDiffs.length !== 1 ? 's have' : ' has'} conflicting changes, it was modified on the original workspace while changes were made on this {currentNoun}. Make sure to resolve these before merging. {/if} {#if hasBehindChanges && hasAheadChanges && !(mergeIntoParent && !canDeployToParent)} You have items behind '{parentWorkspaceId}'. You need to update and test your changes before being able to deploy. Override: Deploy despite {itemsWithBehindChanges.length} outdated item{itemsWithBehindChanges.length !== 1 ? 's' : ''} {/if} {@const hiddenDir = mergeIntoParent ? comparison.hidden_ahead : comparison.hidden_behind} {#if hiddenDir.items.length > 0} {hiddenDir.items.length} {mergeIntoParent ? 'ahead' : 'behind'} item{hiddenDir.items.length !== 1 ? 's' : ''} {hiddenDir.items.length !== 1 ? 'are' : 'is'} excluded from the list below — they are not resolvable as live items and are most likely stale/phantom diff rows:
    {#each hiddenDir.items as it}
  • {hiddenKindLabel(it.kind)} · {it.path}
  • {/each}
{:else if mergeIntoParent ? !comparison.all_ahead_items_visible : !comparison.all_behind_items_visible} {hiddenDir.total} {mergeIntoParent ? 'ahead' : 'behind'} item{hiddenDir.total !== 1 ? 's' : ''} ({formatHiddenByKind(hiddenDir.by_kind)}) {hiddenDir.total !== 1 ? 'are' : 'is'} not visible to your user and {hiddenDir.total !== 1 ? 'are' : 'is'} excluded from the list below. You can still {mergeIntoParent ? 'deploy' : 'update'} the items you can see — share this page with someone who has full access to include the rest. {/if} {/snippet} {#snippet itemSummary(item)} {@const diff = item.diff as WorkspaceItemDiff} {@const key = item.key} {@const editUrl = editUrlFor( diff, diff.exists_in_fork ? currentWorkspaceId : parentWorkspaceId )} {#if isTriggerOrScheduleKind(diff.kind)} {KIND_DISPLAY_NAMES[diff.kind as string] ?? diff.kind} → {diff.path} {:else} {@const oldSummary = mergeIntoParent ? summaryCache[key]?.parent : summaryCache[key]?.current} {@const newSummary = mergeIntoParent ? summaryCache[key]?.current : summaryCache[key]?.parent} {@const existsInBothWorkspaces = !( (diff.exists_in_fork && !diff.exists_in_source) || (!diff.exists_in_fork && diff.exists_in_source) )} {/if} {/snippet} {#snippet itemActions(item)} {@const diff = item.diff as WorkspaceItemDiff} {@const key = item.key} {@const targetOnBehalfOf = getTargetOnBehalfOf(key)} {@const isConflict = diff.ahead > 0 && diff.behind > 0} {@const existsInBothWorkspaces = !( (diff.exists_in_fork && !diff.exists_in_source) || (!diff.exists_in_fork && diff.exists_in_source) )} {#if itemNeedsOnBehalfOfSelection(key, diff.kind)} { onBehalfOfChoice[key] = choice if (details) customOnBehalfOf[key] = details }} kind={diff.kind} canPreserve={canPreserveOnBehalfOf} customValue={customOnBehalfOf[key]?.permissionedAs} /> {/if} {#if diff.kind === 'raw_app'} Raw {/if} {#if hasDraft(diff)} +Draft {/if} {#if diffCreatesInTarget(diff, mergeIntoParent)} New {:else if removesInTarget(diff)} {@const renamedAway = mergeIntoParent && diff.fork_last_event_kind === 'rename_from'} Removes in {deployTargetWorkspace} {/if} {@const ciStatus = getCiTestStatus(diff)} {#if ciStatus === 'pass'} CI pass {:else if ciStatus === 'fail'} CI fail {:else if ciStatus === 'running'} CI {/if} {#if !deploymentStatus[key] || deploymentStatus[key].status != 'deployed'}
{#if isConflict || existsInBothWorkspaces} {#if diff.ahead > 0} {diff.ahead} ahead {/if} {#if diff.behind > 0} {diff.behind} behind {/if} {#if isConflict} Conflict {/if} {/if}
{#if diff.kind === 'resource' || diff.kind === 'variable'} {#if isPinned(diff.kind, diff.path)} workspace-specific {:else} {/if} {/if} {/if} {/snippet} {#snippet footer()} {#if !nothingToAct}
{#if mergeIntoParent && !isArbitraryTarget && !hasOpenDeploymentRequest && !deploymentRequestPanel?.isDialogOpen()} {/if}
{#if !deployPerm.ok} {deployPerm.reason} {/if} {#if !(mergeIntoParent && !canDeployToParent) && hasUnselectedOnBehalfOf} You must set the "on behalf of" user for all items before deploying The "run on behalf of" field defines which user's permissions will be applied during execution. Make sure this is set to an appropriate user before deploying. {/if} {#if deploymentErrorMessage != ''} {deploymentErrorMessage} {/if}
{/if} {/snippet}
{#if !isArbitraryTarget} { hasOpenDeploymentRequest = open }} /> {/if}
{#if !isArbitraryTarget} {/if} {#if pinnedItems.length > 0}
Workspace-specific items

These resources and variables keep their own value in each environment and are excluded from the diff. An item that exists on only one side can be seeded onto the other with "Create in …" (copies the current value, including secrets); it will never overwrite an existing value.

{#each pinnedItems as it (`${it.item_kind}:${it.path}`)} {@const missingSide = it.onCurrent && !it.onParent ? parentWorkspaceId : !it.onCurrent && it.onParent ? currentWorkspaceId : undefined}
{it.item_kind} {it.path} {#if missingSide} {/if}
{/each}
{/if}
{ draftConfirmOpen = false deployChanges() }} onCanceled={() => (draftConfirmOpen = false)} >

{selectedDraftKeys.length} selected item{selectedDraftKeys.length !== 1 ? 's' : ''} {selectedDraftKeys.length !== 1 ? 'have' : 'has'} an undeployed draft. {#if mergeIntoParent} Deploying sends the deployed version, not the draft — those draft changes won't be included. {:else} Updating replaces the deployed version your draft is based on. {/if}

    {#each selectedDraftKeys as k (k)}
  • {k.split(':').slice(1).join(':')}
  • {/each}
(runMigrationsModalOpen = false)} >

Run the deployed migrations in {runMigrationsTargetWorkspaceName} now? These data tables use a separate database, so the schema changes won't apply until the migrations are run.

    {#each runMigrationsDatatables as dt (dt)}
  • {dt}
  • {/each}
{ const it = createConfirm createConfirm = undefined if (it) createOnRemote(it) }} onCanceled={() => (createConfirm = undefined)} >

This copies the current value of {createConfirm?.path} (including any secret value) from {createConfirm?.onCurrent ? currentWorkspaceId : parentWorkspaceId} into {createConfirm?.onCurrent ? parentWorkspaceId : currentWorkspaceId}. It stays workspace-specific afterward, so later promotes won't overwrite it. If it already exists there, it's left untouched and just marked workspace-specific.

{:else}
No comparison data available
{/if}