diff --git a/src/commander.ts b/src/commander.ts index f6fd2407d..cd4437af6 100644 --- a/src/commander.ts +++ b/src/commander.ts @@ -213,6 +213,9 @@ export class Commander { let descriptionPadEnd = 11; jobs.forEach(j => descriptionPadEnd = Math.max(j.description.length, descriptionPadEnd)); + let environmentPadEnd = 11; + jobs.forEach(j => environmentPadEnd = Math.max((j.environment?.name ?? "").length, environmentPadEnd)); + const jobNamePad = parser.jobNamePad; if (!listAll) { @@ -221,15 +224,16 @@ export class Commander { writeStreams.stdout(chalk`{grey ${"name".padEnd(jobNamePad)} ${"description".padEnd(descriptionPadEnd)}} `); writeStreams.stdout(chalk`{grey ${"stage".padEnd(stagePadEnd)} ${"when".padEnd(whenPadEnd)}} `); - writeStreams.stdout(chalk`{grey allow_failure needs}\n`); + writeStreams.stdout(chalk`{grey allow_failure ${"environment".padEnd(environmentPadEnd)} needs}\n`); const renderLine = (job: Job) => { const needs = Commander.formatNeeds(job); const allowFailure = Commander.formatAllowFailure(job.allowFailure); + const environment = job.environment?.name ?? ""; let jobLine = chalk`{blueBright ${job.name.padEnd(jobNamePad)}} ${job.description.padEnd(descriptionPadEnd)} `; - jobLine += chalk`{yellow ${job.stage.padEnd(stagePadEnd)}} ${job.when.padEnd(whenPadEnd)} ${allowFailure.padEnd(11)}`; + jobLine += chalk`{yellow ${job.stage.padEnd(stagePadEnd)}} ${job.when.padEnd(whenPadEnd)} ${allowFailure.padEnd(13)} ${environment.padEnd(environmentPadEnd)}`; if (needs !== null) { - jobLine += chalk` [{blueBright ${needs}}]`; + jobLine += chalk` [{blueBright ${needs}}]`; } writeStreams.stdout(`${jobLine}\n`); }; @@ -267,13 +271,14 @@ export class Commander { jobs = jobs.filter(j => j.when !== "never"); } - writeStreams.stdout("name;stage;when;allowFailure;needs\n"); + writeStreams.stdout("name;stage;when;allowFailure;environment;needs\n"); jobs.forEach((job) => { const needs = Commander.formatNeeds(job); const needsStr = needs === null ? "" : `[${needs.join(",")}]`; const allowFailure = Commander.formatAllowFailure(job.allowFailure); - const row = [job.name, job.stage, job.when, allowFailure, needsStr].join(";"); + const environment = job.environment?.name ?? ""; + const row = [job.name, job.stage, job.when, allowFailure, environment, needsStr].join(";"); writeStreams.stdout(`${row}\n`); }); } diff --git a/tests/test-cases/include-project-file/integration.test.ts b/tests/test-cases/include-project-file/integration.test.ts index edebd3e4e..22b7d1a1a 100644 --- a/tests/test-cases/include-project-file/integration.test.ts +++ b/tests/test-cases/include-project-file/integration.test.ts @@ -60,8 +60,8 @@ test.concurrent("include:project should respect rules specified in included proj const expected = [ - "name description stage when allow_failure needs", - "should execute since rule eval to true test on_success false ", + "name description stage when allow_failure environment needs", + "should execute since rule eval to true test on_success false ", ]; expect(writeStreams.stdoutLines.join("\n")).toEqual(expected.join("\n")); diff --git a/tests/test-cases/list-case/integration.test.ts b/tests/test-cases/list-case/integration.test.ts index 7306c0e40..bafc200fc 100644 --- a/tests/test-cases/list-case/integration.test.ts +++ b/tests/test-cases/list-case/integration.test.ts @@ -17,9 +17,9 @@ test.concurrent("list-case --list", async () => { }, writeStreams); const expected = [ - chalk`{grey name description} {grey stage when } {grey allow_failure needs}`, - chalk`{blueBright test-job } Run Tests {yellow test } on_success false `, - chalk`{blueBright build-job} {yellow build} on_success true [{blueBright test-job}]`, + chalk`{grey ${"name".padEnd(9)} ${"description".padEnd(11)}} {grey ${"stage".padEnd(5)} ${"when".padEnd(10)}} {grey allow_failure ${"environment".padEnd(11)} needs}`, + chalk`{blueBright ${"test-job".padEnd(9)}} ${"Run Tests".padEnd(11)} {yellow ${"test".padEnd(5)}} ${"on_success".padEnd(10)} ${"false".padEnd(13)} ${"".padEnd(11)}`, + chalk`{blueBright ${"build-job".padEnd(9)}} ${"".padEnd(11)} {yellow ${"build".padEnd(5)}} ${"on_success".padEnd(10)} ${"true".padEnd(13)} ${"".padEnd(11)} [{blueBright test-job}]`, ]; expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); }); diff --git a/tests/test-cases/list-csv-case/integration.test.ts b/tests/test-cases/list-csv-case/integration.test.ts index 67a5080fc..2863c0c5d 100644 --- a/tests/test-cases/list-csv-case/integration.test.ts +++ b/tests/test-cases/list-csv-case/integration.test.ts @@ -17,11 +17,11 @@ test.concurrent("list-csv-case --list-csv", async () => { }, writeStreams); const expected = [ - "name;stage;when;allowFailure;needs", - "test-job;test;on_success;false;", - "build-job;build;on_success;true;[test-job]", - "exit-codes-job;build;on_success;[42,137];[]", - "deploy-job;deploy;on_success;[1];", + "name;stage;when;allowFailure;environment;needs", + "test-job;test;on_success;false;;", + "build-job;build;on_success;true;;[test-job]", + "exit-codes-job;build;on_success;[42,137];;[]", + "deploy-job;deploy;on_success;[1];;", ]; expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); }); @@ -37,9 +37,9 @@ test.concurrent("list-csv-case --list-csv colon should add process descriptors w }, writeStreams); const expected = [ - "name;stage;when;allowFailure;needs", - "test-job;test;on_success;false;", - "build-job;build;on_success;true;[test-job]", + "name;stage;when;allowFailure;environment;needs", + "test-job;test;on_success;false;;", + "build-job;build;on_success;true;;[test-job]", ]; expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); }); @@ -53,13 +53,13 @@ test.concurrent("list-csv-case --list", async () => { stateDir: ".gitlab-ci-local-list-csv-case-list", }, writeStreams); - // jobNamePad=14 (exit-codes-job), descriptionPadEnd=11, stagePadEnd=6 (deploy), whenPadEnd=10 + // jobNamePad=14 (exit-codes-job), descriptionPadEnd=11, stagePadEnd=6 (deploy), whenPadEnd=10, environmentPadEnd=11 const expected = [ - chalk`{grey ${"name".padEnd(14)} ${"description".padEnd(11)}} {grey ${"stage".padEnd(6)} ${"when".padEnd(10)}} {grey allow_failure needs}`, - chalk`{blueBright ${"test-job".padEnd(14)}} ${"Run Tests".padEnd(11)} {yellow ${"test".padEnd(6)}} ${"on_success".padEnd(10)} ${"false".padEnd(11)}`, - chalk`{blueBright ${"build-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"build".padEnd(6)}} ${"on_success".padEnd(10)} ${"true".padEnd(11)} [{blueBright test-job}]`, - chalk`{blueBright ${"exit-codes-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"build".padEnd(6)}} ${"on_success".padEnd(10)} ${"[42,137]".padEnd(11)} [{blueBright }]`, - chalk`{blueBright ${"deploy-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"deploy".padEnd(6)}} ${"on_success".padEnd(10)} ${"[1]".padEnd(11)}`, + chalk`{grey ${"name".padEnd(14)} ${"description".padEnd(11)}} {grey ${"stage".padEnd(6)} ${"when".padEnd(10)}} {grey allow_failure ${"environment".padEnd(11)} needs}`, + chalk`{blueBright ${"test-job".padEnd(14)}} ${"Run Tests".padEnd(11)} {yellow ${"test".padEnd(6)}} ${"on_success".padEnd(10)} ${"false".padEnd(13)} ${"".padEnd(11)}`, + chalk`{blueBright ${"build-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"build".padEnd(6)}} ${"on_success".padEnd(10)} ${"true".padEnd(13)} ${"".padEnd(11)} [{blueBright test-job}]`, + chalk`{blueBright ${"exit-codes-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"build".padEnd(6)}} ${"on_success".padEnd(10)} ${"[42,137]".padEnd(13)} ${"".padEnd(11)} [{blueBright }]`, + chalk`{blueBright ${"deploy-job".padEnd(14)}} ${"".padEnd(11)} {yellow ${"deploy".padEnd(6)}} ${"on_success".padEnd(10)} ${"[1]".padEnd(13)} ${"".padEnd(11)}`, ]; expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); }); diff --git a/tests/test-cases/list-environment/.gitlab-ci.yml b/tests/test-cases/list-environment/.gitlab-ci.yml new file mode 100644 index 000000000..c62263618 --- /dev/null +++ b/tests/test-cases/list-environment/.gitlab-ci.yml @@ -0,0 +1,29 @@ +--- +workflow: + rules: + - if: $CI_COMMIT_BRANCH + variables: + DEPLOY_ENV: production + +stages: [test, build, deploy] + +test-job: + stage: test + script: + - echo "testing" + +build-job: + stage: build + needs: [test-job] + environment: + name: staging + script: + - echo "building" + +deploy-job: + stage: deploy + needs: [build-job] + environment: + name: $DEPLOY_ENV + script: + - echo "deploying" diff --git a/tests/test-cases/list-environment/integration.test.ts b/tests/test-cases/list-environment/integration.test.ts new file mode 100644 index 000000000..6d4041a14 --- /dev/null +++ b/tests/test-cases/list-environment/integration.test.ts @@ -0,0 +1,46 @@ +import {WriteStreamsMock} from "../../../src/write-streams.js"; +import {handler} from "../../../src/handler.js"; +import chalk from "chalk-template"; +import {initSpawnSpy} from "../../mocks/utils.mock.js"; +import {WhenStatics} from "../../mocks/when-statics.js"; + +beforeAll(() => { + initSpawnSpy(WhenStatics.all); +}); + +test.concurrent("list-environment --list", async () => { + const writeStreams = new WriteStreamsMock(); + await handler({ + cwd: "tests/test-cases/list-environment/", + list: true, + stateDir: ".gitlab-ci-local-list-environment", + }, writeStreams); + + // jobNamePad=10 (deploy-job), descriptionPadEnd=11, stagePadEnd=6 (deploy), whenPadEnd=10, environmentPadEnd=11 (max("production","staging")=10 < 11) + const expected = [ + chalk`{grey ${"name".padEnd(10)} ${"description".padEnd(11)}} {grey ${"stage".padEnd(6)} ${"when".padEnd(10)}} {grey allow_failure ${"environment".padEnd(11)} needs}`, + chalk`{blueBright ${"test-job".padEnd(10)}} ${"".padEnd(11)} {yellow ${"test".padEnd(6)}} ${"on_success".padEnd(10)} ${"false".padEnd(13)} ${"".padEnd(11)}`, + chalk`{blueBright ${"build-job".padEnd(10)}} ${"".padEnd(11)} {yellow ${"build".padEnd(6)}} ${"on_success".padEnd(10)} ${"false".padEnd(13)} ${"staging".padEnd(11)} [{blueBright test-job}]`, + // This line depends on PR #1833 (workflow:rules:variables) - without it, $DEPLOY_ENV is not resolved to "production" + chalk`{blueBright ${"deploy-job".padEnd(10)}} ${"".padEnd(11)} {yellow ${"deploy".padEnd(6)}} ${"on_success".padEnd(10)} ${"false".padEnd(13)} ${"production".padEnd(11)} [{blueBright build-job}]`, + ]; + expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); +}); + +test.concurrent("list-environment --list-csv", async () => { + const writeStreams = new WriteStreamsMock(); + await handler({ + cwd: "tests/test-cases/list-environment/", + listCsv: true, + stateDir: ".gitlab-ci-local-list-environment-csv", + }, writeStreams); + + const expected = [ + "name;stage;when;allowFailure;environment;needs", + "test-job;test;on_success;false;;", + "build-job;build;on_success;false;staging;[test-job]", + // This line depends on PR #1833 (workflow:rules:variables) - without it, $DEPLOY_ENV is not resolved to "production" + "deploy-job;deploy;on_success;false;production;[build-job]", + ]; + expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected)); +});