conductor

CI task system
git clone git://git.finwo.net/app/conductor
Log | Files | Refs | README | LICENSE

examples.test.js (2632B)


      1 // test/examples.test.js - the shipped examples must stay valid
      2 //
      3 // Documentation that no longer parses is worse than no documentation, so
      4 // every example is compiled as part of the suite.
      5 
      6 import test from 'node:test';
      7 import assert from 'node:assert/strict';
      8 import fs from 'node:fs/promises';
      9 import path from 'node:path';
     10 import { fileURLToPath } from 'node:url';
     11 import { compilePipeline } from '../src/lib/pipeline/index.js';
     12 
     13 const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
     14 const EXAMPLES = path.join(ROOT, 'examples');
     15 
     16 test('every example pipeline compiles', async () => {
     17   const files = (await fs.readdir(EXAMPLES)).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
     18   assert.ok(files.length > 0, 'expected at least one example');
     19 
     20   for (const file of files) {
     21     const text = await fs.readFile(path.join(EXAMPLES, file), 'utf8');
     22     const pipeline = compilePipeline(text, { source: file });
     23     assert.ok(pipeline.tasks.length > 0, `${file} produced no tasks`);
     24   }
     25 });
     26 
     27 test('the distribution example fans in per architecture', async () => {
     28   const text = await fs.readFile(path.join(EXAMPLES, 'distro.conductor.yml'), 'utf8');
     29   const pipeline = compilePipeline(text, { source: 'distro.conductor.yml' });
     30   const tasks = Object.fromEntries(pipeline.tasks.map((j) => [j.name, j]));
     31 
     32   // check, two toolchains, twelve packages, two images, one publish.
     33   assert.equal(pipeline.tasks.length, 18);
     34 
     35   // A package waits only on its own architecture's toolchain.
     36   assert.deepEqual(tasks['package:arch=aarch64,pkg=musl'].needs, ['toolchain:arch=aarch64']);
     37   assert.deepEqual(tasks['package:arch=x86_64,pkg=grub'].needs, ['toolchain:arch=x86_64']);
     38 
     39   // An image waits on every package for its architecture, and no others.
     40   const imageNeeds = tasks['image:arch=x86_64'].needs;
     41   assert.equal(imageNeeds.length, 6);
     42   assert.ok(imageNeeds.every((n) => n.includes('arch=x86_64')));
     43 
     44   // publish has no architecture, so it waits for both, plus check.
     45   assert.equal(tasks.publish.needs.length, 3);
     46   assert.equal(tasks.publish.depth, 3);
     47 });
     48 
     49 test('the node example wires services and features', async () => {
     50   const text = await fs.readFile(path.join(EXAMPLES, 'node-app.conductor.yml'), 'utf8');
     51   const pipeline = compilePipeline(text, { source: 'node-app.conductor.yml' });
     52   const tasks = Object.fromEntries(pipeline.tasks.map((j) => [j.name, j]));
     53 
     54   assert.deepEqual(tasks['test:suite=unit'].services.map((s) => s.alias), ['postgres']);
     55   assert.deepEqual(tasks.image.requires, ['docker']);
     56   assert.equal(tasks['test:suite=integration'].artifacts.when, 'always');
     57 });