Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
100 lines
3.7 KiB
JavaScript
100 lines
3.7 KiB
JavaScript
const { randomUUID } = require('node:crypto');
|
|
|
|
function getApiKey() {
|
|
return process.env.WORKFLOW_HARNESS_API_KEY || process.env.ALGA_API_KEY || '';
|
|
}
|
|
|
|
async function pickOne(ctx, { label, sql, params }) {
|
|
const rows = await ctx.db.query(sql, params);
|
|
if (!rows.length) throw new Error(`Fixture requires ${label} in DB (tenant=${ctx.config.tenantId}).`);
|
|
return rows[0];
|
|
}
|
|
|
|
module.exports = async function run(ctx) {
|
|
const apiKey = getApiKey();
|
|
if (!apiKey) {
|
|
throw new Error('Missing WORKFLOW_HARNESS_API_KEY (or ALGA_API_KEY) for /api/v1 calls.');
|
|
}
|
|
|
|
const tenantId = ctx.config.tenantId;
|
|
const marker = '[fixture project-created-kickoff-tasks]';
|
|
const correlationKey = randomUUID();
|
|
|
|
const client = await pickOne(ctx, {
|
|
label: 'a client',
|
|
sql: `select client_id from clients where tenant = $1 order by created_at asc limit 1`,
|
|
params: [tenantId]
|
|
});
|
|
|
|
const projectName = `Fixture kickoff ${randomUUID()}`;
|
|
const createRes = await ctx.http.request('/api/v1/projects', {
|
|
method: 'POST',
|
|
headers: { 'x-api-key': apiKey },
|
|
json: {
|
|
client_id: client.client_id,
|
|
project_name: projectName,
|
|
create_default_phase: true
|
|
}
|
|
});
|
|
|
|
const projectId = createRes.json?.data?.project_id;
|
|
if (!projectId) throw new Error('Project create response missing data.project_id');
|
|
|
|
ctx.onCleanup(async () => {
|
|
const phaseIds = await ctx.db.query(`select phase_id from project_phases where tenant = $1 and project_id = $2`, [tenantId, projectId]);
|
|
const phaseIdList = phaseIds.map((r) => r.phase_id);
|
|
|
|
if (phaseIdList.length) {
|
|
const taskIds = await ctx.db.query(`select task_id from project_tasks where tenant = $1 and phase_id = any($2::uuid[])`, [
|
|
tenantId,
|
|
phaseIdList
|
|
]);
|
|
const taskIdList = taskIds.map((r) => r.task_id);
|
|
|
|
if (taskIdList.length) {
|
|
await ctx.dbWrite.query(`delete from task_checklist_items where tenant = $1 and task_id = any($2::uuid[])`, [tenantId, taskIdList]);
|
|
await ctx.dbWrite.query(`delete from project_tasks where tenant = $1 and task_id = any($2::uuid[])`, [tenantId, taskIdList]);
|
|
}
|
|
|
|
await ctx.dbWrite.query(`delete from project_phases where tenant = $1 and phase_id = any($2::uuid[])`, [tenantId, phaseIdList]);
|
|
}
|
|
|
|
await ctx.dbWrite.query(`delete from project_ticket_links where tenant = $1 and project_id = $2`, [tenantId, projectId]);
|
|
await ctx.dbWrite.query(`delete from project_status_mappings where tenant = $1 and project_id = $2`, [tenantId, projectId]);
|
|
await ctx.dbWrite.query(`delete from projects where tenant = $1 and project_id = $2`, [tenantId, projectId]);
|
|
});
|
|
|
|
await ctx.http.request('/api/workflow/events', {
|
|
method: 'POST',
|
|
json: {
|
|
eventName: 'PROJECT_CREATED',
|
|
correlationKey,
|
|
payloadSchemaRef: 'payload.ProjectCreated.v1',
|
|
payload: { projectId, fixtureName: 'project-created-kickoff-tasks', correlationKey }
|
|
}
|
|
});
|
|
|
|
const runRow = await ctx.waitForRun({ startedAfter: ctx.triggerStartedAt });
|
|
if (runRow.status !== 'SUCCEEDED') {
|
|
const steps = await ctx.getRunSteps(runRow.run_id);
|
|
throw new Error(`Expected run SUCCEEDED, got ${runRow.status}. Steps: ${JSON.stringify(ctx.summarizeSteps(steps))}`);
|
|
}
|
|
|
|
const tasks = await ctx.db.query(
|
|
`
|
|
select t.task_id, t.task_name
|
|
from project_tasks t
|
|
join project_phases p on p.phase_id = t.phase_id and p.tenant = t.tenant
|
|
where p.tenant = $1 and p.project_id = $2
|
|
order by t.created_at desc
|
|
limit 25
|
|
`,
|
|
[tenantId, projectId]
|
|
);
|
|
|
|
const found = tasks.find((t) => typeof t.task_name === 'string' && t.task_name.includes(marker));
|
|
if (!found) {
|
|
throw new Error(`Expected a project task containing "${marker}" on project ${projectId}. Found ${tasks.length} task(s).`);
|
|
}
|
|
};
|