Publish curated ForgeFlow source from 2ed1787c0b52
This commit is contained in:
commit
f60b269686
254 files changed
+46204
No files matched your search
@@ -0,0 +1,589 @@
|
||||
(() => {
|
||||
if (window.forgeflow) return;
|
||||
|
||||
const wait = (ms = 180) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
const clone = (value) => JSON.parse(JSON.stringify(value));
|
||||
const iso = (offset = 0) => new Date(Date.now() + offset).toISOString();
|
||||
const storage = {
|
||||
get(key) {
|
||||
try {
|
||||
return localStorage.getItem(key);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
set(key, value) {
|
||||
try {
|
||||
localStorage.setItem(key, value);
|
||||
} catch {}
|
||||
},
|
||||
};
|
||||
const repositoryListeners = new Set();
|
||||
const operationListeners = new Set();
|
||||
const updateListeners = new Set();
|
||||
const emitRepositories = () =>
|
||||
repositoryListeners.forEach((listener) =>
|
||||
listener({ reason: "demo-change" }),
|
||||
);
|
||||
const emitOperations = (operations) =>
|
||||
operationListeners.forEach((listener) =>
|
||||
listener({ operations: clone(operations) }),
|
||||
);
|
||||
const randomSha = () =>
|
||||
`${Math.random().toString(16).slice(2)}${Date.now().toString(16)}`
|
||||
.padEnd(40, "a")
|
||||
.slice(0, 40);
|
||||
|
||||
const makeStatus = ({
|
||||
head,
|
||||
branch = "main",
|
||||
ahead = 0,
|
||||
behind = 0,
|
||||
upstream = `origin/${branch}`,
|
||||
files = [],
|
||||
}) => ({
|
||||
branch: { oid: head, head: branch, upstream, ahead, behind },
|
||||
files,
|
||||
counts: {
|
||||
changed: files.length,
|
||||
staged: files.filter((item) => item.staged).length,
|
||||
unstaged: files.filter((item) => item.unstaged).length,
|
||||
conflicts: files.filter((item) => item.conflict).length,
|
||||
untracked: files.filter((item) => item.untracked).length,
|
||||
},
|
||||
clean: files.length === 0,
|
||||
root: "",
|
||||
remoteUrl: "",
|
||||
head,
|
||||
shortHead: head.slice(0, 7),
|
||||
fingerprint: `${head}:${branch}:${ahead}:${behind}:${files.map((item) => `${item.path}:${item.indexCode}${item.worktreeCode}`).join("|")}`,
|
||||
});
|
||||
|
||||
const makeFile = (path, status = "modified", options = {}) => ({
|
||||
path,
|
||||
originalPath: options.originalPath || null,
|
||||
indexCode: options.staged
|
||||
? status === "added"
|
||||
? "A"
|
||||
: status === "deleted"
|
||||
? "D"
|
||||
: "M"
|
||||
: ".",
|
||||
worktreeCode: options.staged
|
||||
? "."
|
||||
: status === "untracked"
|
||||
? "?"
|
||||
: status === "deleted"
|
||||
? "D"
|
||||
: status === "conflict"
|
||||
? "U"
|
||||
: "M",
|
||||
staged: Boolean(options.staged),
|
||||
unstaged: !options.staged,
|
||||
untracked: status === "untracked",
|
||||
conflict: status === "conflict",
|
||||
status,
|
||||
});
|
||||
|
||||
const profile = (id, name, environment, options = {}) => ({
|
||||
id,
|
||||
name,
|
||||
environment,
|
||||
provider: "gitea-actions",
|
||||
branch: options.branch || "main",
|
||||
workflowFile: options.workflowFile || "deploy.yml",
|
||||
rollbackWorkflowFile: options.rollbackWorkflowFile ?? "rollback.yml",
|
||||
healthcheckUrl:
|
||||
options.healthcheckUrl || `https://${environment}.internal/health`,
|
||||
statusUrl:
|
||||
options.statusUrl ||
|
||||
`https://${environment}.internal/.well-known/forgeflow`,
|
||||
confirmationRequired: options.confirmationRequired !== false,
|
||||
inputs: {},
|
||||
state: {
|
||||
liveSha: options.liveSha || null,
|
||||
previousSha: options.previousSha || null,
|
||||
healthy: options.healthy ?? null,
|
||||
healthConfigured: true,
|
||||
statusConfigured: true,
|
||||
healthStatus: options.healthy === false ? 503 : 200,
|
||||
healthLatencyMs: 42,
|
||||
checkedAt: options.checkedAt || iso(-120000),
|
||||
},
|
||||
});
|
||||
|
||||
const sshProfile = (id, name, environment, options = {}) => ({
|
||||
id, name, environment, provider: "ssh-unraid", branch: options.branch || "main",
|
||||
serverId: "demo-unraid", remoteFolder: options.remoteFolder || name,
|
||||
deploymentMode: "server-git", composeFiles: ["compose.yml"],
|
||||
composeProject: options.composeProject || String(options.remoteFolder || name).toLowerCase(),
|
||||
composeServices: options.composeServices || [String(options.remoteFolder || name).toLowerCase()],
|
||||
containerName: options.containerName || options.remoteFolder || name,
|
||||
generatedCompose: false, adoptedFromServer: true, serverSourceOfTruth: true,
|
||||
confirmationRequired: true,
|
||||
serverGitAccess: { configured: options.accessConfigured !== false, keyFingerprint: "SHA256:demo", hostFingerprint: "SHA256:gitea", configuredAt: iso(-3600000) },
|
||||
state: {
|
||||
liveSha: options.liveSha || null, giteaSha: options.giteaSha || options.liveSha || null,
|
||||
previousSha: options.previousSha || null, healthy: options.healthy ?? true,
|
||||
containerRunning: true, runtimeVerification: "verified", matchesGitea: options.matchesGitea ?? true,
|
||||
checkedAt: iso(-120000), dockerMan: { templateExists: true, webUi: true, icon: true },
|
||||
},
|
||||
});
|
||||
|
||||
const now = iso();
|
||||
const defaultPreferences = {
|
||||
autoRefresh: true,
|
||||
repositoryPollSeconds: 4,
|
||||
operationPollSeconds: 5,
|
||||
fetchIntervalMinutes: 10,
|
||||
preferredCloneProtocol: "https",
|
||||
diagnosticsEnabled: true,
|
||||
diagnosticLevel: "info",
|
||||
logRetentionDays: 14,
|
||||
maxLogFileMb: 8,
|
||||
};
|
||||
|
||||
let state = {
|
||||
schemaVersion: 8,
|
||||
setupComplete: storage.get("forgeflow-demo-setup") !== "false",
|
||||
appearance: storage.get("forgeflow-theme") || "dark",
|
||||
gitea: {
|
||||
baseUrl: "https://gitea.internal",
|
||||
user: { login: "jens", full_name: "Jens" },
|
||||
hasToken: true,
|
||||
},
|
||||
workspaceRoots: ["C:\\Development"],
|
||||
repositoryMappings: {},
|
||||
deploymentProfiles: {},
|
||||
deploymentStates: {},
|
||||
favorites: [
|
||||
"jens/microsoft-cloud-operations-platform",
|
||||
"jens/unraid-appops-gateway",
|
||||
],
|
||||
updates: {
|
||||
owner: "Jens",
|
||||
repo: "ForgeFlow",
|
||||
branch: "main",
|
||||
autoCheck: true,
|
||||
lastCheckedAt: null,
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
id: "server-unraid",
|
||||
name: "Unraid",
|
||||
host: "192.168.1.10",
|
||||
port: 22,
|
||||
username: "root",
|
||||
authType: "privateKey",
|
||||
basePath: "/mnt/user/appdata",
|
||||
privateKeyPath: "C:\\Users\\your-name\\.ssh\\id_ed25519",
|
||||
hostFingerprint: "SHA256:demo",
|
||||
hasPassword: false,
|
||||
hasPassphrase: false,
|
||||
},
|
||||
],
|
||||
preferences: { ...defaultPreferences },
|
||||
operations: [
|
||||
{
|
||||
id: "op-success",
|
||||
type: "deployment",
|
||||
action: "deploy",
|
||||
status: "success",
|
||||
repository: "jens/microsoft-cloud-operations-platform",
|
||||
profileId: "profile-mcop-prod",
|
||||
profileName: "Production",
|
||||
environment: "production",
|
||||
workflowFile: "deploy.yml",
|
||||
branch: "main",
|
||||
sha: "b82f91ab0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
shortSha: "b82f91a",
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
stages: [
|
||||
{ id: "requested", label: "Requested", status: "complete" },
|
||||
{ id: "verified", label: "Verified", status: "complete" },
|
||||
{ id: "queued", label: "Workflow queued", status: "complete" },
|
||||
{ id: "runner", label: "Runner execution", status: "complete" },
|
||||
{ id: "healthcheck", label: "Healthcheck", status: "complete" },
|
||||
{ id: "complete", label: "Complete", status: "complete" },
|
||||
],
|
||||
logs: [
|
||||
"[info] Exact commit verified.",
|
||||
"[job] deploy: success",
|
||||
"[ok] Server reports b82f91a and healthcheck returned 200.",
|
||||
],
|
||||
run: {
|
||||
id: 48,
|
||||
runNumber: 48,
|
||||
status: "completed",
|
||||
conclusion: "success",
|
||||
name: "ForgeFlow deployment",
|
||||
},
|
||||
runUrl:
|
||||
"https://gitea.internal/jens/microsoft-cloud-operations-platform/actions/runs/48",
|
||||
},
|
||||
{
|
||||
id: "op-failed",
|
||||
type: "deployment",
|
||||
action: "deploy",
|
||||
status: "failed",
|
||||
repository: "jens/portfolio",
|
||||
profileId: "profile-portfolio",
|
||||
profileName: "Production",
|
||||
environment: "production",
|
||||
workflowFile: "deploy.yml",
|
||||
branch: "main",
|
||||
sha: "a7f2e1c1bb6147fc8b6633d2b08500c93402a719",
|
||||
shortSha: "a7f2e1c",
|
||||
createdAt: iso(-86400000),
|
||||
updatedAt: iso(-86300000),
|
||||
failure: { stage: "healthcheck", message: "Healthcheck returned 502." },
|
||||
stages: [
|
||||
{ id: "requested", label: "Requested", status: "complete" },
|
||||
{ id: "verified", label: "Verified", status: "complete" },
|
||||
{ id: "queued", label: "Workflow queued", status: "complete" },
|
||||
{ id: "runner", label: "Runner execution", status: "complete" },
|
||||
{ id: "healthcheck", label: "Healthcheck", status: "failed" },
|
||||
{ id: "complete", label: "Complete", status: "failed" },
|
||||
],
|
||||
logs: ["[job] deploy: success", "[error] Healthcheck returned 502."],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
let repositories = [
|
||||
{
|
||||
id: 1,
|
||||
name: "microsoft-cloud-operations-platform",
|
||||
fullName: "jens/microsoft-cloud-operations-platform",
|
||||
owner: { login: "jens" },
|
||||
description: "Tenant-aware Microsoft cloud operations console.",
|
||||
private: true,
|
||||
defaultBranch: "main",
|
||||
htmlUrl:
|
||||
"https://gitea.internal/jens/microsoft-cloud-operations-platform",
|
||||
cloneUrl:
|
||||
"https://gitea.internal/jens/microsoft-cloud-operations-platform.git",
|
||||
sshUrl: "git@gitea.internal:jens/microsoft-cloud-operations-platform.git",
|
||||
updatedAt: now,
|
||||
localPath: "C:\\Development\\Microsoft-Cloud-Operations-Platform",
|
||||
localStatus: makeStatus({
|
||||
head: "b82f91ab0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
}),
|
||||
linkState: "linked",
|
||||
deploymentProfiles: [
|
||||
profile("profile-mcop-prod", "Production", "production", {
|
||||
liveSha: "72bd10eb0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
previousSha: "6ac991ab0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
healthy: true,
|
||||
}),
|
||||
profile("profile-mcop-stage", "Staging", "staging", {
|
||||
liveSha: "b82f91ab0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
previousSha: "72bd10eb0173cd4346ca0f0f7dcc3e8182cc8fd0",
|
||||
healthy: true,
|
||||
confirmationRequired: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "vacancyradar",
|
||||
fullName: "jens/vacancyradar",
|
||||
owner: { login: "jens" },
|
||||
description: "Local-first vacancy intelligence cockpit.",
|
||||
private: true,
|
||||
defaultBranch: "main",
|
||||
htmlUrl: "https://gitea.internal/jens/vacancyradar",
|
||||
cloneUrl: "https://gitea.internal/jens/vacancyradar.git",
|
||||
sshUrl: "git@gitea.internal:jens/vacancyradar.git",
|
||||
updatedAt: now,
|
||||
localPath: "C:\\Development\\VacancyRadar",
|
||||
localStatus: makeStatus({
|
||||
head: "c9182d0d28318c8cf0af109edc054732426aadf1",
|
||||
branch: "feature/deployment-api",
|
||||
files: [
|
||||
makeFile("src/api/deploy.ts", "added", { staged: true }),
|
||||
makeFile("src/main.tsx"),
|
||||
makeFile("src/components/Sidebar.tsx"),
|
||||
],
|
||||
}),
|
||||
linkState: "linked",
|
||||
deploymentProfiles: [
|
||||
profile("profile-vr", "Production", "production", {
|
||||
liveSha: "c117ab9d28318c8cf0af109edc054732426aadf1",
|
||||
previousSha: "b1f57aad28318c8cf0af109edc054732426aadf1",
|
||||
healthy: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "unraid-appops-gateway",
|
||||
fullName: "jens/unraid-appops-gateway",
|
||||
owner: { login: "jens" },
|
||||
description: "Safe operations gateway for Unraid and Portainer.",
|
||||
private: true,
|
||||
defaultBranch: "main",
|
||||
htmlUrl: "https://gitea.internal/jens/unraid-appops-gateway",
|
||||
cloneUrl: "https://gitea.internal/jens/unraid-appops-gateway.git",
|
||||
sshUrl: "git@gitea.internal:jens/unraid-appops-gateway.git",
|
||||
updatedAt: now,
|
||||
localPath: "C:\\Development\\Unraid-AppOps-Gateway",
|
||||
localStatus: makeStatus({
|
||||
head: "f2d1e0a1bb6147fc8b6633d2b08500c93402a719",
|
||||
ahead: 2,
|
||||
}),
|
||||
linkState: "linked",
|
||||
deploymentProfiles: [
|
||||
profile("profile-appops", "Production", "production", {
|
||||
liveSha: "8ac731b1bb6147fc8b6633d2b08500c93402a719",
|
||||
previousSha: "7bc198a1bb6147fc8b6633d2b08500c93402a719",
|
||||
healthy: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "support-bundle-collector",
|
||||
fullName: "jens/support-bundle-collector",
|
||||
owner: { login: "jens" },
|
||||
description: "Privacy-aware Windows support bundle collector.",
|
||||
private: true,
|
||||
defaultBranch: "main",
|
||||
htmlUrl: "https://gitea.internal/jens/support-bundle-collector",
|
||||
cloneUrl: "https://gitea.internal/jens/support-bundle-collector.git",
|
||||
sshUrl: "git@gitea.internal:jens/support-bundle-collector.git",
|
||||
updatedAt: now,
|
||||
localPath: null,
|
||||
localStatus: null,
|
||||
linkState: "remote-only",
|
||||
deploymentProfiles: [],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "portfolio",
|
||||
fullName: "jens/portfolio",
|
||||
owner: { login: "jens" },
|
||||
description: "Professional infrastructure and automation portfolio.",
|
||||
private: false,
|
||||
defaultBranch: "main",
|
||||
htmlUrl: "https://gitea.internal/jens/portfolio",
|
||||
cloneUrl: "https://gitea.internal/jens/portfolio.git",
|
||||
sshUrl: "git@gitea.internal:jens/portfolio.git",
|
||||
updatedAt: now,
|
||||
localPath: "C:\\Development\\portfolio",
|
||||
localStatus: makeStatus({
|
||||
head: "a7f2e1c1bb6147fc8b6633d2b08500c93402a719",
|
||||
behind: 1,
|
||||
}),
|
||||
linkState: "linked",
|
||||
deploymentProfiles: [
|
||||
sshProfile("profile-portfolio", "Production", "production", {
|
||||
remoteFolder: "Portfolio",
|
||||
containerName: "Portfolio",
|
||||
liveSha: "4c20dd11bb6147fc8b6633d2b08500c93402a719",
|
||||
giteaSha: "a7f2e1c1bb6147fc8b6633d2b08500c93402a719",
|
||||
previousSha: "31adfe11bb6147fc8b6633d2b08500c93402a719",
|
||||
healthy: false,
|
||||
matchesGitea: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const diffs = {
|
||||
"src/api/deploy.ts": `diff --git a/src/api/deploy.ts b/src/api/deploy.ts\nnew file mode 100644\n--- /dev/null\n+++ b/src/api/deploy.ts\n@@ -0,0 +1,18 @@\n+export interface DeploymentRequest {\n+ environment: 'staging' | 'production';\n+ commitSha: string;\n+}\n+\n+export async function deploy(request: DeploymentRequest) {\n+ return api.post('/deployments', request);\n+}`,
|
||||
"src/main.tsx": `diff --git a/src/main.tsx b/src/main.tsx\nindex 45ad1a2..939fc17 100644\n--- a/src/main.tsx\n+++ b/src/main.tsx\n@@ -24,8 +24,9 @@ import { Router } from './routes';\n-const API_ENDPOINT = 'http://localhost:3000';\n+const API_ENDPOINT = process.env.VITE_API_URL || '/api';\n+const DEPLOY_VERSION = '1.0.4-rc1';`,
|
||||
"src/components/Sidebar.tsx": `diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx\nindex a7bbd82..bf21e90 100644\n--- a/src/components/Sidebar.tsx\n+++ b/src/components/Sidebar.tsx\n@@ -31,6 +31,7 @@ export function Sidebar() {\n+ <NavItem to="/deployments">Deployments</NavItem>`,
|
||||
};
|
||||
|
||||
const findRepo = (localPath) =>
|
||||
repositories.find((item) => item.localPath === localPath);
|
||||
const findProfileRepo = (profileId) =>
|
||||
repositories.find((item) =>
|
||||
item.deploymentProfiles.some((entry) => entry.id === profileId),
|
||||
);
|
||||
const syncState = () => {
|
||||
state.deploymentProfiles = {};
|
||||
state.deploymentStates = {};
|
||||
state.repositoryMappings = {};
|
||||
for (const repository of repositories) {
|
||||
if (repository.localPath)
|
||||
state.repositoryMappings[repository.fullName.toLowerCase()] =
|
||||
repository.localPath;
|
||||
state.deploymentProfiles[repository.fullName.toLowerCase()] =
|
||||
repository.deploymentProfiles.map(
|
||||
({ state: profileState, ...entry }) => entry,
|
||||
);
|
||||
for (const entry of repository.deploymentProfiles)
|
||||
if (entry.state) state.deploymentStates[entry.id] = clone(entry.state);
|
||||
}
|
||||
};
|
||||
const recompute = (repository) => {
|
||||
const status = repository.localStatus;
|
||||
if (status) {
|
||||
status.counts = {
|
||||
changed: status.files.length,
|
||||
staged: status.files.filter((item) => item.staged).length,
|
||||
unstaged: status.files.filter((item) => item.unstaged).length,
|
||||
conflicts: status.files.filter((item) => item.conflict).length,
|
||||
untracked: status.files.filter((item) => item.untracked).length,
|
||||
};
|
||||
status.clean = status.files.length === 0;
|
||||
status.shortHead = status.head.slice(0, 7);
|
||||
status.branch.oid = status.head;
|
||||
}
|
||||
repository.favorite = state.favorites.includes(
|
||||
repository.fullName.toLowerCase(),
|
||||
);
|
||||
repository.readyToDeploy = Boolean(
|
||||
repository.localPath &&
|
||||
status?.clean &&
|
||||
status.branch.upstream &&
|
||||
status.branch.ahead === 0 &&
|
||||
status.branch.behind === 0 &&
|
||||
repository.deploymentProfiles.some(
|
||||
(entry) => entry.branch === status.branch.head,
|
||||
),
|
||||
);
|
||||
repository.attention =
|
||||
!repository.localPath ||
|
||||
Boolean(
|
||||
status?.counts.conflicts ||
|
||||
status?.branch.behind ||
|
||||
status?.branch.ahead ||
|
||||
status?.counts.changed,
|
||||
);
|
||||
repository.attentionReason = !repository.localPath
|
||||
? "No local folder linked"
|
||||
: status?.counts.conflicts
|
||||
? `${status.counts.conflicts} conflict(s)`
|
||||
: status?.counts.changed
|
||||
? `${status.counts.changed} local change(s)`
|
||||
: status?.branch.behind
|
||||
? `${status.branch.behind} commit(s) behind remote`
|
||||
: status?.branch.ahead
|
||||
? `${status.branch.ahead} unpushed commit(s)`
|
||||
: null;
|
||||
repository.preferredCloneUrl =
|
||||
state.preferences.preferredCloneProtocol === "ssh"
|
||||
? repository.sshUrl
|
||||
: repository.cloneUrl;
|
||||
};
|
||||
const snapshot = () => {
|
||||
repositories.forEach(recompute);
|
||||
syncState();
|
||||
return clone(repositories);
|
||||
};
|
||||
syncState();
|
||||
|
||||
const commitHistory = [
|
||||
{
|
||||
sha: "c9182d0d28318c8cf0af109edc054732426aadf1",
|
||||
shortSha: "c9182d0",
|
||||
author: "Jens",
|
||||
date: now,
|
||||
subject: "feat: add deployment provider contract",
|
||||
},
|
||||
{
|
||||
sha: "1fa7399d28318c8cf0af109edc054732426aadf1",
|
||||
shortSha: "1fa7399",
|
||||
author: "Jens",
|
||||
date: iso(-86400000),
|
||||
subject: "refactor: consolidate repository state",
|
||||
},
|
||||
{
|
||||
sha: "a251a11d28318c8cf0af109edc054732426aadf1",
|
||||
shortSha: "a251a11",
|
||||
author: "Jens",
|
||||
date: iso(-172800000),
|
||||
subject: "docs: define deployment safety gates",
|
||||
},
|
||||
];
|
||||
const branchesByRepo = new Map();
|
||||
const stashesByRepo = new Map();
|
||||
|
||||
function updateOperation(operation) {
|
||||
state.operations = [
|
||||
clone(operation),
|
||||
...state.operations.filter((item) => item.id !== operation.id),
|
||||
].slice(0, 250);
|
||||
emitOperations([operation]);
|
||||
return clone(operation);
|
||||
}
|
||||
|
||||
function advanceOperation(operation) {
|
||||
if (
|
||||
!operation ||
|
||||
["success", "failed", "cancelled", "rolled-back"].includes(
|
||||
operation.status,
|
||||
)
|
||||
)
|
||||
return operation;
|
||||
operation.demoPolls = (operation.demoPolls || 0) + 1;
|
||||
if (operation.demoPolls === 1) {
|
||||
operation.status = "running";
|
||||
operation.run = {
|
||||
id: 81,
|
||||
runNumber: 81,
|
||||
status: "running",
|
||||
conclusion: null,
|
||||
name:
|
||||
operation.action === "rollback"
|
||||
? "ForgeFlow rollback"
|
||||
: "ForgeFlow deployment",
|
||||
};
|
||||
operation.runUrl = `https://gitea.internal/${operation.repository}/actions/runs/81`;
|
||||
operation.stages.find((item) => item.id === "queued").status = "complete";
|
||||
operation.stages.find((item) => item.id === "runner").status = "active";
|
||||
operation.jobs = [
|
||||
{
|
||||
id: 201,
|
||||
name: operation.action === "rollback" ? "rollback" : "deploy",
|
||||
status: "running",
|
||||
conclusion: null,
|
||||
},
|
||||
];
|
||||
operation.logs.push(`[job] ${operation.jobs[0].name}: running`);
|
||||
} else if (operation.demoPolls >= 2) {
|
||||
operation.status =
|
||||
operation.action === "rollback" ? "rolled-back" : "success";
|
||||
operation.stages.forEach((item) => {
|
||||
item.status = "complete";
|
||||
});
|
||||
operation.jobs = [
|
||||
{
|
||||
id: 201,
|
||||
name: operation.action === "rollback" ? "rollback" : "deploy",
|
||||
status: "completed",
|
||||
conclusion: "success",
|
||||
},
|
||||
];
|
||||
operation.logs.push(
|
||||
"[ok] Runner completed successfully.",
|
||||
`[ok] Server status endpoint confirms ${operation.shortSha}.`,
|
||||
);
|
||||
const repository = repositories.find(
|
||||
(item) => item.fullName === operation.repository,
|
||||
);
|
||||
const targetProfile = repository?.deploymentProfiles.find(
|
||||
(item) => item.id === operation.profileId,
|
||||
);
|
||||
if (targetProfile) {
|
||||
const oldLive = targetProfile.state.liveSha;
|
||||
targetProfile.state.previousSha = oldLive;
|
||||
targetProfile.state.liveSha = operation.sha;
|
||||
targetProfile.state.healthy = true;
|
||||
targetProfile.state.checkedAt = iso();
|
||||
}
|
||||
}
|
||||
operation.updatedAt = iso();
|
||||
return operation;
|
||||
}
|
||||
|
||||
const bridgeContext = { wait, clone, iso, storage, repositoryListeners, operationListeners, updateListeners, emitRepositories, emitOperations, randomSha, now, profile, state, repositories, recompute, snapshot, commitHistory, advanceOperation, syncState, diffs, findRepo, findProfileRepo, branchesByRepo, stashesByRepo, updateOperation };
|
||||
window.forgeflow = Object.freeze({
|
||||
...createMockRepositoryBridge(bridgeContext),
|
||||
...createMockDeploymentBridge(bridgeContext),
|
||||
});
|
||||
})();
|
||||
Reference in new issue
Block a user