Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/gitlab.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,15 @@ Two jobs stay inactive until you set them up in the project's CI/CD settings:
marked Protected is only visible on protected branches, so protect the default branch or leave
the variable unprotected; otherwise the job silently stays away.
- **`renovate`** needs a CI/CD variable `RENOVATE_TOKEN` (same scopes) and a pipeline schedule,
for example weekly. The schedule alone decides how often Renovate runs.
for example weekly. The schedule alone decides how often Renovate runs. It opens one merge
request for minor and patch updates, one per major, and an issue named Dependency Dashboard.
- Renovate leaves alone the images of repokeeper's own jobs in `.gitlab-ci.yml` (`node`,
`renovate/renovate`, the .NET SDK): the standard names their versions and `repokeeper update`
moves them. A job of your own in that file that uses one of these images is not updated
either.
- Changelogs in its merge requests come from github.com, which answers few requests without a
token. A CI/CD variable `GITHUB_COM_TOKEN` (a GitHub token with no scopes at all) lifts that
limit; without it Renovate works and says in the dashboard that release notes were skipped.

## Project settings: `repokeeper gitlab apply`

Expand Down
16 changes: 16 additions & 0 deletions src/platforms/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ const ciKey = (module: string, key: string, value: unknown): Output => ({
/** Image of the jobs that only run tools, whatever Node.js versions the project tests on. */
const TOOL_IMAGE = "node:24";

/**
* The images repokeeper's own jobs name with a version Renovate would move: the tool image, Renovate itself and
* the .NET SDK of the dotnet and powershell jobs. Images named through a CI variable or by a moving tag
* (`latest`, `stable`) are not in its reach.
*/
export const MANAGED_IMAGES = ["node", "renovate/renovate", "mcr.microsoft.com/dotnet/sdk"] as const;

/** The node stack's CI inputs, as the GitHub reusable workflow receives them, as a GitLab job. */
function nodeJob(input: Record<string, string>): Record<string, unknown> {
const pm = input["package-manager"] ?? "npm";
Expand Down Expand Up @@ -165,6 +172,15 @@ export const gitlabPlatform: PlatformAdapter = {
{ matchUpdateTypes: ["minor", "patch"], groupName: "minor and patch updates" },
// @types/node majors track the Node.js line a project runs on, which the project chooses
{ matchPackageNames: ["@types/node"], matchUpdateTypes: ["major"], enabled: false },
// The images of repokeeper's own jobs are the standard's to move, with `repokeeper update`. A merge
// request that bumps one edits a managed key: `repokeeper check` reports it, the next update takes it
// back, and Renovate (pinned to the patch) would open one every week.
{
matchManagers: ["gitlabci"],
matchFileNames: [CI_FILE],
matchPackageNames: [...MANAGED_IMAGES],
enabled: false,
},
],
}),
},
Expand Down
46 changes: 46 additions & 0 deletions test/platforms-gitlab-stacks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
import { run } from "../src/cli.js";
import { MANAGED_IMAGES } from "../src/platforms/gitlab.js";
import { SCRIPT_ANALYZER_VERSION, SHFMT_VERSION } from "../src/platforms/gitlab-jobs.js";
import { PACKAGE_VERSION, TOOL_VERSIONS } from "../src/version.js";
import { capture, tempDir } from "./helpers.js";
Expand Down Expand Up @@ -70,6 +71,23 @@ function expectBump(project: Awaited<ReturnType<typeof onGitlab>>, files: string
expect(project.releaseScript).toContain(`@semantic-release/exec@${TOOL_VERSIONS.semanticReleaseExec}`);
}

/** Every fixture: each stack, and the second package manager or build tool of the ones that have two. */
const FIXTURES = [
"node",
"node-pnpm",
"go",
"python",
"rust",
"ruby",
"php",
"dart",
"java-gradle",
"java-maven",
"kotlin",
"dotnet",
"script",
] as const;

describe("gitlab ci for the other stacks", () => {
it("python: one job per version, pip or uv", async () => {
const pip = await onGitlab("python");
Expand Down Expand Up @@ -244,6 +262,34 @@ describe("gitlab ci for the other stacks", () => {
expect(github).toContain(`-RequiredVersion ${SCRIPT_ANALYZER_VERSION} `);
});

// Renovate reads .gitlab-ci.yml too. An image one of repokeeper's jobs names with a version is the standard's
// to move, so Renovate is told to leave it: otherwise it opens a merge request against a managed key.
it("names for Renovate every image its own jobs pin to a version", async () => {
const pinned = new Set<string>();
for (const fixture of FIXTURES) {
const project = await onGitlab(fixture);
for (const job of Object.values(project.ci)) {
const image = (job as Partial<Job>).image;
if (!image) continue;
const at = image.lastIndexOf(":");
const [name, tag] = at < 0 ? [image, "latest"] : [image.slice(0, at), image.slice(at + 1)];
// a CI variable or a moving tag is nothing Renovate can raise
if (tag.includes("${") || tag === "latest" || tag === "stable") continue;
pinned.add(name);
}
const renovate = JSON.parse(await readFile(join(project.dir, "renovate.json"), "utf8")) as {
packageRules: Array<Record<string, unknown>>;
};
expect(renovate.packageRules.at(-1)).toEqual({
matchManagers: ["gitlabci"],
matchFileNames: [".gitlab-ci.yml"],
matchPackageNames: [...MANAGED_IMAGES],
enabled: false,
});
}
expect([...pinned].sort()).toEqual([...MANAGED_IMAGES].sort());
});

it("says that os has no effect, whichever stack names one", async () => {
const python = await onGitlab("python", {}, " python:\n os: [ubuntu-latest, windows-latest]");
const c = capture(python.dir);
Expand Down
6 changes: 6 additions & 0 deletions test/platforms-gitlab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ describe("gitlab dependency updates", () => {
packageRules: [
{ matchUpdateTypes: ["minor", "patch"], groupName: "minor and patch updates" },
{ matchPackageNames: ["@types/node"], matchUpdateTypes: ["major"], enabled: false },
{
matchManagers: ["gitlabci"],
matchFileNames: [".gitlab-ci.yml"],
matchPackageNames: ["node", "renovate/renovate", "mcr.microsoft.com/dotnet/sdk"],
enabled: false,
},
],
});
expect(files(depsModule.outputs(gitlabContext()))[".github/dependabot.yml"]).toBeUndefined();
Expand Down
Loading