Skip to content

Commit de52548

Browse files
committed
New optional .gitlab-ci-local-ignores file to list file to ignore to sync with jobs.
The file could also be specified on command line. Format should follow the `rsync` ignore format. Also never sync the `.git/lfs` directory which, if it exists, is usually huge.
1 parent cfc7aaf commit de52548

10 files changed

Lines changed: 68 additions & 6 deletions

File tree

src/argv.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export function injectGclVariableEnvVars (argv: {variable?: string[]; [key: stri
6060
export class Argv {
6161
static readonly default = {
6262
"variablesFile": ".gitlab-ci-local-variables.yml",
63+
"ignoresFile": ".gitlab-ci-local-ignores",
6364
"inputsFile": ".gitlab-ci-local-inputs.yml",
6465
"evaluateRuleChanges": true,
6566
"ignoreSchemaPaths": [] as string[],
@@ -170,6 +171,10 @@ export class Argv {
170171
return this.map.get("inputsFile") ?? Argv.default.inputsFile;
171172
}
172173

174+
get ignoresFile (): string {
175+
return this.map.get("ignoresFile") ?? Argv.default.ignoresFile;
176+
}
177+
173178
get evaluateRuleChanges (): boolean {
174179
return this.map.get("evaluateRuleChanges") ?? Argv.default.evaluateRuleChanges;
175180
}

src/handler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export async function handler (args: any, writeStreams: WriteStreams, jobs: Job[
8181
pipelineIid = await state.getPipelineIid(cwd, stateDir);
8282
}
8383
parser = await Parser.create(argv, writeStreams, pipelineIid, jobs);
84-
await Utils.rsyncTrackedFiles(cwd, stateDir, ".docker");
84+
await Utils.rsyncTrackedFiles(cwd, stateDir, `${cwd}/${argv.ignoresFile}`, ".docker");
8585
await Commander.runJobs(argv, parser, writeStreams);
8686
if (argv.needs || argv.onlyNeeds) {
8787
writeStreams.stderr(chalk`{grey pipeline finished} in {grey ${prettyHrtime(process.hrtime(time))}}\n`);
@@ -94,7 +94,7 @@ export async function handler (args: any, writeStreams: WriteStreams, jobs: Job[
9494
const time = process.hrtime();
9595
const pipelineIid = await state.getPipelineIid(cwd, stateDir);
9696
parser = await Parser.create(argv, writeStreams, pipelineIid, jobs);
97-
await Utils.rsyncTrackedFiles(cwd, stateDir, ".docker");
97+
await Utils.rsyncTrackedFiles(cwd, stateDir, `${cwd}/${argv.ignoresFile}`, ".docker");
9898
await Commander.runJobsInStage(argv, parser, writeStreams);
9999
writeStreams.stderr(chalk`{grey pipeline finished} in {grey ${prettyHrtime(process.hrtime(time))}}\n`);
100100
} else {
@@ -105,7 +105,7 @@ export async function handler (args: any, writeStreams: WriteStreams, jobs: Job[
105105
const time = process.hrtime();
106106
const pipelineIid = await state.incrementPipelineIid(cwd, stateDir);
107107
parser = await Parser.create(argv, writeStreams, pipelineIid, jobs);
108-
await Utils.rsyncTrackedFiles(cwd, stateDir, ".docker");
108+
await Utils.rsyncTrackedFiles(cwd, stateDir, `${cwd}/${argv.ignoresFile}`, ".docker");
109109
await Commander.runPipeline(argv, parser, writeStreams);
110110
if (childPipelineDepth == 0) writeStreams.stderr(chalk`{grey pipeline finished} in {grey ${prettyHrtime(process.hrtime(time))}}\n`);
111111
}

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ process.on("SIGUSR2", async () => {
138138
requiresArg: true,
139139
default: Argv.default.inputsFile,
140140
})
141+
.option("ignores-file", {
142+
type: "string",
143+
description: "Path to a ignores file",
144+
requiresArg: true,
145+
default: Argv.default.ignoresFile,
146+
})
141147
.option("completion", {
142148
type: "boolean",
143149
description: "Generate tab completion script",

src/job.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -920,7 +920,7 @@ If you know what you're doing and would like to suppress this warning, use one o
920920

921921
// Copy git tracked files to build folder if shell isolation enabled.
922922
if (!imageName && this.argv.shellIsolation) {
923-
await Utils.rsyncTrackedFiles(cwd, stateDir, `${safeJobName}`);
923+
await Utils.rsyncTrackedFiles(cwd, stateDir, `${cwd}/${this.argv.ignoresFile}`, `${safeJobName}`);
924924
}
925925

926926
if (this.interactive) {

src/utils.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,19 @@ export class Utils {
377377
return !relative.startsWith("..");
378378
}
379379

380-
static async rsyncTrackedFiles (cwd: string, stateDir: string, target: string): Promise<{hrdeltatime: [number, number]}> {
380+
static async rsyncTrackedFiles (cwd: string, stateDir: string, ignoresFile: string, target: string): Promise<{hrdeltatime: [number, number]}> {
381381
const time = process.hrtime();
382382
await fs.mkdirp(`${cwd}/${stateDir}/builds/${target}`);
383-
await Utils.bash(`rsync -a --delete-excluded --delete --exclude-from=<(git ls-files -o --directory | awk '{print "/"$0}') --exclude ${stateDir}/ ./ ${stateDir}/builds/${target}/`, cwd);
383+
const cmd = [
384+
"rsync -a --delete-excluded --delete",
385+
`--exclude-from=<(git ls-files -o --directory | awk '{print "/"$0}')`, // eslint-disable-line @stylistic/quotes
386+
`--exclude-from=<(cat ${Utils.safeBashString(ignoresFile)} 2>/dev/null || true)`,
387+
"--exclude .git/lfs",
388+
`--exclude ${stateDir}/`,
389+
"./",
390+
`${stateDir}/builds/${target}/`,
391+
].join(" ");
392+
await Utils.bash(cmd, cwd);
384393
return {hrdeltatime: process.hrtime(time)};
385394
}
386395

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
test-job:
3+
script:
4+
- tree -a
5+
- find $STATE_DIR -type f -name '*.txt' -print | wc -l
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*-big-*
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {WriteStreamsMock} from "../../../src/write-streams.js";
2+
import {handler} from "../../../src/handler.js";
3+
4+
const cwd = "tests/test-cases/project-ignores-file";
5+
const ignoresFile = "gitlab-ci-local-ignores-test-job";
6+
7+
test.concurrent("project-no-ignores-file", async () => {
8+
const writeStreams = new WriteStreamsMock();
9+
const stateDir = ".gitlab-ci-local-no-ignores-file";
10+
await handler({
11+
cwd,
12+
job: ["test-job"],
13+
noColor: true,
14+
stateDir,
15+
variable: [`STATE_DIR=${stateDir}`],
16+
}, writeStreams);
17+
const expected = ["test-job > 2"];
18+
expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected));
19+
});
20+
21+
test.concurrent("project-ignores-file", async () => {
22+
const writeStreams = new WriteStreamsMock();
23+
const stateDir = ".gitlab-ci-local-ignores-file";
24+
await handler({
25+
cwd,
26+
job: ["test-job"],
27+
ignoresFile,
28+
noColor: true,
29+
stateDir,
30+
variable: [`STATE_DIR=${stateDir}`],
31+
}, writeStreams);
32+
const expected = ["test-job > 1"];
33+
expect(writeStreams.stdoutLines).toEqual(expect.arrayContaining(expected));
34+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
I should be ignored
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
I should be rsynced

0 commit comments

Comments
 (0)