From 71afe186c9d24cdab009db11dffa1e6a61af8361 Mon Sep 17 00:00:00 2001 From: Dennis Wielepsky Date: Tue, 24 Sep 2024 18:21:17 +0200 Subject: [PATCH] add new configuration parser --- biome.json | 5 +- src/configuration.mjs | 44 +++++++++ src/configuration.spec.js | 182 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 src/configuration.mjs create mode 100644 src/configuration.spec.js diff --git a/biome.json b/biome.json index 53668c9..7f49e17 100644 --- a/biome.json +++ b/biome.json @@ -19,7 +19,10 @@ "linter": { "enabled": true, "rules": { - "recommended": true + "recommended": true, + "performance": { + "noDelete": "off" + } } }, "javascript": { diff --git a/src/configuration.mjs b/src/configuration.mjs new file mode 100644 index 0000000..265dd79 --- /dev/null +++ b/src/configuration.mjs @@ -0,0 +1,44 @@ +const mustReadEnv = (variable) => { + const val = process.env[variable]; + if (val === undefined || val.length === 0) { + throw new Error(); + } + + return val; +}; + +function readBoolean(variable) { + return process.env[variable] === "true" || process.env[variable] === "1"; +} + +function readInt(variable) { + if (process.env[variable] === undefined) { + return undefined; + } + + return Number.parseInt(process.env[variable]); +} + +export function configuration() { + const defaultDelay = 3600; + const config = { + github: { + username: mustReadEnv("GITHUB_USERNAME"), + token: process.env.GITHUB_TOKEN, + skipForks: readBoolean("SKIP_FORKS"), + privateRepositories: readBoolean("MIRROR_PRIVATE_REPOSITORIES"), + }, + gitea: { + url: mustReadEnv("GITEA_URL"), + token: mustReadEnv("GITEA_TOKEN"), + }, + dryRun: readBoolean("DRY_RUN"), + delay: readInt("DELAY") ?? defaultDelay, + }; + + if (config.github.privateRepositories && config.github.token === undefined) { + throw new Error(); + } + + return config; +} diff --git a/src/configuration.spec.js b/src/configuration.spec.js new file mode 100644 index 0000000..ca7887c --- /dev/null +++ b/src/configuration.spec.js @@ -0,0 +1,182 @@ +import { configuration } from "./configuration.mjs"; + +const aGithubUsername = "A_GITHUB_USERNAME"; +const aGiteaUrl = "https://gitea.url"; +const aGiteaToken = "secret-gitea-token"; +const aGithubToken = "a-github-token"; + +const variables = [ + "DELAY", + "DRY_RUN", + "GITEA_TOKEN", + "GITEA_URL", + "GITHUB_TOKEN", + "GITHUB_USERNAME", + "MIRROR_PRIVATE_REPOSITORIES", + "SKIP_FORKS", +]; + +function provideMandatoryVariables() { + process.env.GITHUB_USERNAME = aGithubUsername; + process.env.GITEA_URL = aGiteaUrl; + process.env.GITEA_TOKEN = aGiteaToken; +} + +const defaultDelay = 3600; +describe("configuration", () => { + beforeEach(() => { + for (const variable of variables) { + delete process.env[variable]; + } + }); + + it("reads configuration with default values", () => { + process.env.GITHUB_USERNAME = aGithubUsername; + process.env.GITEA_URL = aGiteaUrl; + process.env.GITEA_TOKEN = aGiteaToken; + + const config = configuration(); + + expect(config.github.username).toEqual(aGithubUsername); + expect(config.github.token).toBeUndefined(); + expect(config.github.skipForks).toEqual(false); + + expect(config.gitea.url).toEqual(aGiteaUrl); + expect(config.gitea.token).toEqual(aGiteaToken); + + expect(config.delay).toEqual(defaultDelay); + }); + + it("requires gitea url", () => { + provideMandatoryVariables(); + delete process.env.GITEA_URL; + + expect(() => configuration()).toThrow(); + }); + + it("requires gitea token", () => { + provideMandatoryVariables(); + delete process.env.GITEA_TOKEN; + + expect(() => configuration()).toThrow(); + }); + + it("requires github username", () => { + provideMandatoryVariables(); + delete process.env.GITHUB_USERNAME; + + expect(() => configuration()).toThrow(); + }); + + it("reads github token", () => { + provideMandatoryVariables(); + process.env.GITHUB_TOKEN = aGithubToken; + + const config = configuration(); + + expect(config.github.token).toEqual(aGithubToken); + }); + + describe("dry run flag", () => { + it("treats true as true", () => { + provideMandatoryVariables(); + process.env.DRY_RUN = "true"; + + const config = configuration(); + + expect(config.dryRun).toEqual(true); + }); + + it("treats 1 as true", () => { + provideMandatoryVariables(); + process.env.DRY_RUN = "1"; + + const config = configuration(); + + expect(config.dryRun).toEqual(true); + }); + + it("treats missing flag as false", () => { + provideMandatoryVariables(); + + const config = configuration(); + + expect(config.dryRun).toEqual(false); + }); + }); + + describe("skip forks flag", () => { + it("treats true as true", () => { + provideMandatoryVariables(); + process.env.SKIP_FORKS = "true"; + + const config = configuration(); + + expect(config.github.skipForks).toEqual(true); + }); + + it("treats 1 as true", () => { + provideMandatoryVariables(); + process.env.SKIP_FORKS = "1"; + + const config = configuration(); + + expect(config.github.skipForks).toEqual(true); + }); + + it("treats missing flag as false", () => { + provideMandatoryVariables(); + + const config = configuration(); + + expect(config.github.skipForks).toEqual(false); + }); + }); + + describe("mirror private repositories flag", () => { + it("treats true as true", () => { + provideMandatoryVariables(); + process.env.GITHUB_TOKEN = aGithubToken; + process.env.MIRROR_PRIVATE_REPOSITORIES = "true"; + + const config = configuration(); + + expect(config.github.privateRepositories).toEqual(true); + }); + + it("treats 1 as true", () => { + provideMandatoryVariables(); + process.env.GITHUB_TOKEN = aGithubToken; + + process.env.MIRROR_PRIVATE_REPOSITORIES = "1"; + + const config = configuration(); + + expect(config.github.privateRepositories).toEqual(true); + }); + + it("treats missing flag as false", () => { + provideMandatoryVariables(); + + const config = configuration(); + + expect(config.github.privateRepositories).toEqual(false); + }); + }); + + it("requires a github token on private repository mirroring", () => { + provideMandatoryVariables(); + process.env.MIRROR_PRIVATE_REPOSITORIES = "true"; + + expect(() => configuration()).toThrow(); + }); + + it("parses delay", () => { + provideMandatoryVariables(); + process.env.DELAY = "1200"; + + const config = configuration(); + + expect(config.delay).toEqual(1200); + }); +});