CODE_OF_CONDUCT
for more information.
+We are committed to making open source an enjoyable and respectful experience for our community. See [`CODE_OF_CONDUCT`](CODE_OF_CONDUCT.md) for more information.
## License
-This project is distributed under the Apache-2.0 license. See LICENSE
for more information.
+This project is distributed under the Apache-2.0 license. See [`LICENSE`](LICENSE) for more information.
## Contact
@@ -116,4 +116,4 @@ If you can't access Slack, you can also [subscribe to our mailing list](mailto:g
Join our [fortnightly Zoom meeting](https://zoom.us/j/97235277537?pwd=aDJsaE8zcDJpYW1vZHJmSTJ0RXNZUT09) on Monday, 11AM EST (odd week numbers). Send an e-mail to [help@finos.org](mailto:help@finos.org) to get a calendar invitation.
-Otherwise, if you have a deeper query or require more support, please [raise an issue](https://github.com/finos/git-proxy/issues).
+Otherwise, if you have a deeper query or require more support, please [raise an issue](https://github.com/finos/git-proxy/issues).
diff --git a/config.schema.json b/config.schema.json
index 4e9622ca0..78cc005c8 100644
--- a/config.schema.json
+++ b/config.schema.json
@@ -24,6 +24,30 @@
"description": "Provide domains to use alternative to the defaults",
"type": "object"
},
+ "rateLimit": {
+ "description": "API Rate limiting configuration.",
+ "type": "object",
+ "properties": {
+ "windowMs": {
+ "type": "number",
+ "description": "How long to remember requests for, in milliseconds (default 10 mins)."
+ },
+ "limit": {
+ "type": "number",
+ "description": "How many requests to allow (default 150)."
+ },
+ "statusCode": {
+ "type": "number",
+ "description": "HTTP status code after limit is reached (default is 429)."
+ },
+ "message": {
+ "type": "string",
+ "description": "Response to return after limit is reached."
+ }
+ },
+ "required": ["windowMs", "limit"],
+ "additionalProperties": false
+ },
"privateOrganizations": {
"description": "Pattern searches for listed private organizations are disabled",
"type": "array"
@@ -88,6 +112,18 @@
"cert": { "type": "string" }
},
"required": ["enabled", "key", "cert"]
+ },
+ "configurationSources": {
+ "enabled": { "type": "boolean" },
+ "reloadIntervalSeconds": { "type": "number" },
+ "merge": { "type": "boolean" },
+ "sources": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "description": "Configuration source"
+ }
+ }
}
},
"definitions": {
diff --git a/cypress/e2e/autoApproved.cy.js b/cypress/e2e/autoApproved.cy.js
index ae67f3ecd..65d9d65a1 100644
--- a/cypress/e2e/autoApproved.cy.js
+++ b/cypress/e2e/autoApproved.cy.js
@@ -2,6 +2,8 @@ import moment from 'moment';
describe('Auto-Approved Push Test', () => {
beforeEach(() => {
+ cy.login('admin', 'admin');
+
cy.intercept('GET', '/api/v1/push/123', {
statusCode: 200,
body: {
@@ -45,7 +47,7 @@ describe('Auto-Approved Push Test', () => {
});
it('should display auto-approved message and verify tooltip contains the expected timestamp', () => {
- cy.visit('/admin/push/123');
+ cy.visit('/dashboard/push/123');
cy.wait('@getPush');
diff --git a/cypress/e2e/login.cy.js b/cypress/e2e/login.cy.js
index 590506f62..25d80e438 100644
--- a/cypress/e2e/login.cy.js
+++ b/cypress/e2e/login.cy.js
@@ -19,6 +19,18 @@ describe('Login page', () => {
cy.get('[data-test="login"]').should('exist');
});
+ it('should redirect to repo list on valid login', () => {
+ cy.intercept('GET', '**/api/auth/me').as('getUser');
+
+ cy.get('[data-test="username"]').type('admin');
+ cy.get('[data-test="password"]').type('admin');
+ cy.get('[data-test="login"]').click();
+
+ cy.wait('@getUser');
+
+ cy.url().should('include', '/dashboard/repo');
+ })
+
describe('OIDC login button', () => {
it('should exist', () => {
cy.get('[data-test="oidc-login"]').should('exist');
@@ -26,8 +38,10 @@ describe('Login page', () => {
// Validates that OIDC is configured correctly
it('should redirect to /oidc', () => {
+ // Set intercept first, since redirect on click can be quick
+ cy.intercept('GET', '/api/auth/oidc').as('oidcRedirect');
cy.get('[data-test="oidc-login"]').click();
- cy.url().should('include', '/oidc');
+ cy.wait('@oidcRedirect');
});
});
});
diff --git a/cypress/e2e/repo.cy.js b/cypress/e2e/repo.cy.js
index 32c7d1cab..411397128 100644
--- a/cypress/e2e/repo.cy.js
+++ b/cypress/e2e/repo.cy.js
@@ -1,6 +1,8 @@
describe('Repo', () => {
beforeEach(() => {
- cy.visit('/admin/repo');
+ cy.login('admin', 'admin');
+
+ cy.visit('/dashboard/repo');
// prevent failures on 404 request and uncaught promises
cy.on('uncaught:exception', () => false);
@@ -18,7 +20,7 @@ describe('Repo', () => {
cy
// find the entry for finos/test-repo
- .get('a[href="/admin/repo/test-repo"]')
+ .get('a[href="/dashboard/repo/test-repo"]')
// take it's parent row
.closest('tr')
// find the nearby span containing Code we can click to open the tooltip
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
index aa3b052c2..751eabdfa 100644
--- a/cypress/support/commands.js
+++ b/cypress/support/commands.js
@@ -29,9 +29,13 @@
Cypress.Commands.add('login', (username, password) => {
cy.session([username, password], () => {
cy.visit('/login');
+ cy.intercept('GET', '**/api/auth/me').as('getUser');
+
cy.get('[data-test=username]').type(username);
cy.get('[data-test=password]').type(password);
cy.get('[data-test=login]').click();
- cy.url().should('contain', '/admin/profile');
+
+ cy.wait('@getUser');
+ cy.url().should('include', '/dashboard/repo');
});
});
diff --git a/experimental/li-cli/package-lock.json b/experimental/li-cli/package-lock.json
index 9b3276498..5636e7646 100644
--- a/experimental/li-cli/package-lock.json
+++ b/experimental/li-cli/package-lock.json
@@ -9,22 +9,22 @@
"version": "0.0.1",
"license": "Apache-2.0",
"dependencies": {
- "@inquirer/prompts": "^7.3.3",
- "yaml": "^2.7.0",
+ "@inquirer/prompts": "^7.5.0",
+ "yaml": "^2.7.1",
"yargs": "^17.7.2",
- "zod": "^3.24.2"
+ "zod": "^3.24.4"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
- "@types/node": "^22.13.10",
+ "@types/node": "^22.15.12",
"@types/yargs": "^17.0.33",
"jest": "^29.7.0",
"rimraf": "^6.0.1",
- "ts-jest": "^29.2.6",
+ "ts-jest": "^29.3.2",
"ts-node": "^10.9.2",
- "tsc-alias": "^1.8.11",
+ "tsc-alias": "^1.8.16",
"tslib": "^2.8.1",
- "typescript": "^5.8.2"
+ "typescript": "^5.8.3"
}
},
"node_modules/@ampproject/remapping": {
@@ -563,14 +563,14 @@
}
},
"node_modules/@inquirer/checkbox": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.3.tgz",
- "integrity": "sha512-KU1MGwf24iABJjGESxhyj+/rlQYSRoCfcuHDEHXfZ1DENmbuSRfyrUb+LLjHoee5TNOFKwaFxDXc5/zRwJUPMQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.5.tgz",
+ "integrity": "sha512-swPczVU+at65xa5uPfNP9u3qx/alNwiaykiI/ExpsmMSQW55trmZcwhYWzw/7fj+n6Q8z1eENvR7vFfq9oPSAQ==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
+ "@inquirer/core": "^10.1.10",
"@inquirer/figures": "^1.0.11",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/type": "^3.0.6",
"ansi-escapes": "^4.3.2",
"yoctocolors-cjs": "^2.1.2"
},
@@ -587,13 +587,13 @@
}
},
"node_modules/@inquirer/confirm": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.7.tgz",
- "integrity": "sha512-Xrfbrw9eSiHb+GsesO8TQIeHSMTP0xyvTCeeYevgZ4sKW+iz9w/47bgfG9b0niQm+xaLY2EWPBINUPldLwvYiw==",
+ "version": "5.1.9",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.9.tgz",
+ "integrity": "sha512-NgQCnHqFTjF7Ys2fsqK2WtnA8X1kHyInyG+nMIuHowVTIgIuS10T4AznI/PvbqSpJqjCUqNBlKGh1v3bwLFL4w==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5"
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6"
},
"engines": {
"node": ">=18"
@@ -608,13 +608,13 @@
}
},
"node_modules/@inquirer/core": {
- "version": "10.1.8",
- "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.8.tgz",
- "integrity": "sha512-HpAqR8y715zPpM9e/9Q+N88bnGwqqL8ePgZ0SMv/s3673JLMv3bIkoivGmjPqXlEgisUksSXibweQccUwEx4qQ==",
+ "version": "10.1.10",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.10.tgz",
+ "integrity": "sha512-roDaKeY1PYY0aCqhRmXihrHjoSW2A00pV3Ke5fTpMCkzcGF64R8e0lw3dK+eLEHwS4vB5RnW1wuQmvzoRul8Mw==",
"license": "MIT",
"dependencies": {
"@inquirer/figures": "^1.0.11",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/type": "^3.0.6",
"ansi-escapes": "^4.3.2",
"cli-width": "^4.1.0",
"mute-stream": "^2.0.0",
@@ -649,13 +649,13 @@
}
},
"node_modules/@inquirer/editor": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.8.tgz",
- "integrity": "sha512-UkGKbMFlQw5k4ZLjDwEi5z8NIVlP/3DAlLHta0o0pSsdpPThNmPtUL8mvGCHUaQtR+QrxR9yRYNWgKMsHkfIUA==",
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.10.tgz",
+ "integrity": "sha512-5GVWJ+qeI6BzR6TIInLP9SXhWCEcvgFQYmcRG6d6RIlhFjM5TyG18paTGBgRYyEouvCmzeco47x9zX9tQEofkw==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6",
"external-editor": "^3.1.0"
},
"engines": {
@@ -671,13 +671,13 @@
}
},
"node_modules/@inquirer/expand": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.10.tgz",
- "integrity": "sha512-leyBouGJ77ggv51Jb/OJmLGGnU2HYc13MZ2iiPNLwe2VgFgZPVqsrRWSa1RAHKyazjOyvSNKLD1B2K7A/iWi1g==",
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.12.tgz",
+ "integrity": "sha512-jV8QoZE1fC0vPe6TnsOfig+qwu7Iza1pkXoUJ3SroRagrt2hxiL+RbM432YAihNR7m7XnU0HWl/WQ35RIGmXHw==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6",
"yoctocolors-cjs": "^2.1.2"
},
"engines": {
@@ -702,13 +702,13 @@
}
},
"node_modules/@inquirer/input": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.7.tgz",
- "integrity": "sha512-rCQAipJNA14UTH84df/z4jDJ9LZ54H6zzuCAi7WZ0qVqx3CSqLjfXAMd5cpISIxbiHVJCPRB81gZksq6CZsqDg==",
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.9.tgz",
+ "integrity": "sha512-mshNG24Ij5KqsQtOZMgj5TwEjIf+F2HOESk6bjMwGWgcH5UBe8UoljwzNFHqdMbGYbgAf6v2wU/X9CAdKJzgOA==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5"
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6"
},
"engines": {
"node": ">=18"
@@ -723,13 +723,13 @@
}
},
"node_modules/@inquirer/number": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.10.tgz",
- "integrity": "sha512-GLsdnxzNefjCJUmWyjaAuNklHgDpCTL4RMllAVhVvAzBwRW9g38eZ5tWgzo1lirtSDTpsh593hqXVhxvdrjfwA==",
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.12.tgz",
+ "integrity": "sha512-7HRFHxbPCA4e4jMxTQglHJwP+v/kpFsCf2szzfBHy98Wlc3L08HL76UDiA87TOdX5fwj2HMOLWqRWv9Pnn+Z5Q==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5"
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6"
},
"engines": {
"node": ">=18"
@@ -744,13 +744,13 @@
}
},
"node_modules/@inquirer/password": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.10.tgz",
- "integrity": "sha512-JC538ujqeYKkFqLoWZ0ILBteIUO2yajBMVEUZSxjl9x6fiEQtM+I5Rca7M2D8edMDbyHLnXifGH1hJZdh8V5rA==",
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.12.tgz",
+ "integrity": "sha512-FlOB0zvuELPEbnBYiPaOdJIaDzb2PmJ7ghi/SVwIHDDSQ2K4opGBkF+5kXOg6ucrtSUQdLhVVY5tycH0j0l+0g==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6",
"ansi-escapes": "^4.3.2"
},
"engines": {
@@ -766,21 +766,21 @@
}
},
"node_modules/@inquirer/prompts": {
- "version": "7.3.3",
- "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.3.3.tgz",
- "integrity": "sha512-QS1AQgJ113iE/nmym03yKZKHvGjVWwkGZT3B1yKrrMG0bJKQg1jUkntFP8aPd2FUQzu/nga7QU2eDpzIP5it0Q==",
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.5.0.tgz",
+ "integrity": "sha512-tk8Bx7l5AX/CR0sVfGj3Xg6v7cYlFBkEahH+EgBB+cZib6Fc83dwerTbzj7f2+qKckjIUGsviWRI1d7lx6nqQA==",
"license": "MIT",
"dependencies": {
- "@inquirer/checkbox": "^4.1.3",
- "@inquirer/confirm": "^5.1.7",
- "@inquirer/editor": "^4.2.8",
- "@inquirer/expand": "^4.0.10",
- "@inquirer/input": "^4.1.7",
- "@inquirer/number": "^3.0.10",
- "@inquirer/password": "^4.0.10",
- "@inquirer/rawlist": "^4.0.10",
- "@inquirer/search": "^3.0.10",
- "@inquirer/select": "^4.0.10"
+ "@inquirer/checkbox": "^4.1.5",
+ "@inquirer/confirm": "^5.1.9",
+ "@inquirer/editor": "^4.2.10",
+ "@inquirer/expand": "^4.0.12",
+ "@inquirer/input": "^4.1.9",
+ "@inquirer/number": "^3.0.12",
+ "@inquirer/password": "^4.0.12",
+ "@inquirer/rawlist": "^4.1.0",
+ "@inquirer/search": "^3.0.12",
+ "@inquirer/select": "^4.2.0"
},
"engines": {
"node": ">=18"
@@ -795,13 +795,13 @@
}
},
"node_modules/@inquirer/rawlist": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.10.tgz",
- "integrity": "sha512-vOQbQkmhaCsF2bUmjoyRSZJBz77UnIF/F3ZS2LMgwbgyaG2WgwKHh0WKNj0APDB72WDbZijhW5nObQbk+TnbcA==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.0.tgz",
+ "integrity": "sha512-6ob45Oh9pXmfprKqUiEeMz/tjtVTFQTgDDz1xAMKMrIvyrYjAmRbQZjMJfsictlL4phgjLhdLu27IkHNnNjB7g==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/core": "^10.1.10",
+ "@inquirer/type": "^3.0.6",
"yoctocolors-cjs": "^2.1.2"
},
"engines": {
@@ -817,14 +817,14 @@
}
},
"node_modules/@inquirer/search": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.10.tgz",
- "integrity": "sha512-EAVKAz6P1LajZOdoL+R+XC3HJYSU261fbJzO4fCkJJ7UPFcm+nP+gzC+DDZWsb2WK9PQvKsnaKiNKsY8B6dBWQ==",
+ "version": "3.0.12",
+ "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.12.tgz",
+ "integrity": "sha512-H/kDJA3kNlnNIjB8YsaXoQI0Qccgf0Na14K1h8ExWhNmUg2E941dyFPrZeugihEa9AZNW5NdsD/NcvUME83OPQ==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
+ "@inquirer/core": "^10.1.10",
"@inquirer/figures": "^1.0.11",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/type": "^3.0.6",
"yoctocolors-cjs": "^2.1.2"
},
"engines": {
@@ -840,14 +840,14 @@
}
},
"node_modules/@inquirer/select": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.10.tgz",
- "integrity": "sha512-Tg8S9nESnCfISu5tCZSuXpXq0wHuDVimj7xyHstABgR34zcJnLdq/VbjB2mdZvNAMAehYBnNzSjxB06UE8LLAA==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.0.tgz",
+ "integrity": "sha512-KkXQ4aSySWimpV4V/TUJWdB3tdfENZUU765GjOIZ0uPwdbGIG6jrxD4dDf1w68uP+DVtfNhr1A92B+0mbTZ8FA==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.1.8",
+ "@inquirer/core": "^10.1.10",
"@inquirer/figures": "^1.0.11",
- "@inquirer/type": "^3.0.5",
+ "@inquirer/type": "^3.0.6",
"ansi-escapes": "^4.3.2",
"yoctocolors-cjs": "^2.1.2"
},
@@ -864,9 +864,9 @@
}
},
"node_modules/@inquirer/type": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz",
- "integrity": "sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==",
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.6.tgz",
+ "integrity": "sha512-/mKVCtVpyBu3IDarv0G+59KC4stsD5mDsGpYh+GKs1NZT88Jh52+cuoA1AtLk2Q0r/quNl+1cSUyLRHBFeD0XA==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -1575,13 +1575,13 @@
}
},
"node_modules/@types/node": {
- "version": "22.13.10",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz",
- "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==",
+ "version": "22.15.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.12.tgz",
+ "integrity": "sha512-K0fpC/ZVeb8G9rm7bH7vI0KAec4XHEhBam616nVJCV51bKzJ6oA3luG4WdKoaztxe70QaNjS/xBmcDLmr4PiGw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~6.20.0"
+ "undici-types": "~6.21.0"
}
},
"node_modules/@types/stack-utils": {
@@ -2637,6 +2637,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/get-tsconfig": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
+ "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -4348,6 +4361,16 @@
"node": ">=8"
}
},
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
"node_modules/resolve.exports": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
@@ -4749,9 +4772,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.2.6",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.6.tgz",
- "integrity": "sha512-yTNZVZqc8lSixm+QGVFcPe6+yj7+TWZwIesuOWvfcn4B9bz5x4NDzVCQQjOs7Hfouu36aEqfEbo9Qpo+gq8dDg==",
+ "version": "29.3.2",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.3.2.tgz",
+ "integrity": "sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4763,6 +4786,7 @@
"lodash.memoize": "^4.1.2",
"make-error": "^1.3.6",
"semver": "^7.7.1",
+ "type-fest": "^4.39.1",
"yargs-parser": "^21.1.1"
},
"bin": {
@@ -4810,6 +4834,19 @@
"node": ">=10"
}
},
+ "node_modules/ts-jest/node_modules/type-fest": {
+ "version": "4.40.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.1.tgz",
+ "integrity": "sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
@@ -4855,14 +4892,15 @@
}
},
"node_modules/tsc-alias": {
- "version": "1.8.11",
- "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.11.tgz",
- "integrity": "sha512-2DuEQ58A9Rj2NE2c1+/qaGKlshni9MCK95MJzRGhQG0CYLw0bE/ACgbhhTSf/p1svLelwqafOd8stQate2bYbg==",
+ "version": "1.8.16",
+ "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.16.tgz",
+ "integrity": "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==",
"dev": true,
"license": "MIT",
"dependencies": {
"chokidar": "^3.5.3",
"commander": "^9.0.0",
+ "get-tsconfig": "^4.10.0",
"globby": "^11.0.4",
"mylas": "^2.1.9",
"normalize-path": "^3.0.0",
@@ -4870,6 +4908,9 @@
},
"bin": {
"tsc-alias": "dist/bin/index.js"
+ },
+ "engines": {
+ "node": ">=16.20.2"
}
},
"node_modules/tslib": {
@@ -4902,9 +4943,9 @@
}
},
"node_modules/typescript": {
- "version": "5.8.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
- "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4916,9 +4957,9 @@
}
},
"node_modules/undici-types": {
- "version": "6.20.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
- "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
+ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"devOptional": true,
"license": "MIT"
},
@@ -5093,9 +5134,9 @@
"license": "ISC"
},
"node_modules/yaml": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
- "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz",
+ "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
@@ -5167,9 +5208,9 @@
}
},
"node_modules/zod": {
- "version": "3.24.2",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz",
- "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==",
+ "version": "3.24.4",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz",
+ "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
diff --git a/experimental/li-cli/package.json b/experimental/li-cli/package.json
index 6bb723fb0..794e86446 100644
--- a/experimental/li-cli/package.json
+++ b/experimental/li-cli/package.json
@@ -13,21 +13,21 @@
"test": "jest --forceExit --detectOpenHandles"
},
"dependencies": {
- "@inquirer/prompts": "^7.3.3",
- "yaml": "^2.7.0",
+ "@inquirer/prompts": "^7.5.0",
+ "yaml": "^2.7.1",
"yargs": "^17.7.2",
- "zod": "^3.24.2"
+ "zod": "^3.24.4"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
- "@types/node": "^22.13.10",
+ "@types/node": "^22.15.12",
"@types/yargs": "^17.0.33",
"jest": "^29.7.0",
"rimraf": "^6.0.1",
- "ts-jest": "^29.2.6",
+ "ts-jest": "^29.3.2",
"ts-node": "^10.9.2",
- "tsc-alias": "^1.8.11",
+ "tsc-alias": "^1.8.16",
"tslib": "^2.8.1",
- "typescript": "^5.8.2"
+ "typescript": "^5.8.3"
}
}
diff --git a/package-lock.json b/package-lock.json
index 3052eaddc..0c3c36e2e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@finos/git-proxy",
- "version": "1.10.0",
+ "version": "1.14.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@finos/git-proxy",
- "version": "1.10.0",
+ "version": "1.14.0",
"license": "Apache-2.0",
"workspaces": [
"./packages/git-proxy-cli"
@@ -25,6 +25,7 @@
"connect-mongo": "^5.1.0",
"cors": "^2.8.5",
"diff2html": "^3.4.33",
+ "env-paths": "^2.2.1",
"express": "^4.18.2",
"express-http-proxy": "^2.0.0",
"express-rate-limit": "^7.1.5",
@@ -87,12 +88,13 @@
"mocha": "^10.8.2",
"nyc": "^17.0.0",
"prettier": "^3.0.0",
+ "proxyquire": "^2.1.3",
"sinon": "^19.0.2",
"ts-mocha": "^11.1.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.3",
"typescript": "^5.7.3",
- "vite": "4.5.5",
+ "vite": "^4.5.13",
"vite-tsconfig-paths": "^5.1.4"
},
"optionalDependencies": {
@@ -1034,27 +1036,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
- "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
+ "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.26.0"
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
- "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
+ "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.0"
+ "@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1202,9 +1204,10 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.23.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz",
- "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+ "license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -1213,15 +1216,15 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
+ "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/code-frame": "^7.26.2",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1247,9 +1250,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
- "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
+ "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4649,9 +4652,9 @@
"dev": true
},
"node_modules/axios": {
- "version": "1.8.4",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
- "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+ "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -6167,7 +6170,6 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -7257,6 +7259,20 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/fill-keys": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
+ "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-object": "~1.0.1",
+ "merge-descriptors": "~1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -8410,12 +8426,16 @@
}
},
"node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -8596,6 +8616,16 @@
"node": ">=8"
}
},
+ "node_modules/is-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
+ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -10192,6 +10222,13 @@
"node": ">=10"
}
},
+ "node_modules/module-not-found-error": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz",
+ "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
@@ -11337,6 +11374,39 @@
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
+ "node_modules/proxyquire": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz",
+ "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-keys": "^1.0.2",
+ "module-not-found-error": "^1.0.1",
+ "resolve": "^1.11.1"
+ }
+ },
+ "node_modules/proxyquire/node_modules/resolve": {
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.16.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -13800,9 +13870,9 @@
}
},
"node_modules/vite": {
- "version": "4.5.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz",
- "integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==",
+ "version": "4.5.13",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.13.tgz",
+ "integrity": "sha512-Hgp8IF/yZDzKsN1hQWOuQZbrKiaFsbQud+07jJ8h9m9PaHWkpvZ5u55Xw5yYjWRXwRQ4jwFlJvY7T7FUJG9MCA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -14309,7 +14379,7 @@
"license": "Apache-2.0",
"dependencies": {
"@finos/git-proxy": "file:../..",
- "axios": "^1.8.4",
+ "axios": "^1.9.0",
"yargs": "^17.7.2"
},
"bin": {
diff --git a/package.json b/package.json
index 757dfbd92..cde79f2fc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@finos/git-proxy",
- "version": "1.10.0",
+ "version": "1.14.0",
"description": "Deploy custom push protections and policies on top of Git.",
"scripts": {
"cli": "node ./packages/git-proxy-cli/index.js",
@@ -8,8 +8,11 @@
"clientinstall": "npm install --prefix client",
"server": "tsx index.ts",
"start": "concurrently \"npm run server\" \"npm run client\"",
- "build": "vite build",
- "build-ts": "tsc",
+ "build": "npm run build-ui && npm run build-lib",
+ "build-ui": "vite build",
+ "build-lib": "./scripts/build-for-publish.sh",
+ "restore-lib": "./scripts/undo-build.sh",
+ "check-types": "tsc",
"test": "NODE_ENV=test ts-mocha './test/*.js' --exit",
"test-coverage": "nyc npm run test",
"test-coverage-ci": "nyc --reporter=lcovonly --reporter=text npm run test",
@@ -47,6 +50,7 @@
"connect-mongo": "^5.1.0",
"cors": "^2.8.5",
"diff2html": "^3.4.33",
+ "env-paths": "^2.2.1",
"express": "^4.18.2",
"express-http-proxy": "^2.0.0",
"express-rate-limit": "^7.1.5",
@@ -105,12 +109,13 @@
"mocha": "^10.8.2",
"nyc": "^17.0.0",
"prettier": "^3.0.0",
+ "proxyquire": "^2.1.3",
"sinon": "^19.0.2",
"ts-mocha": "^11.1.0",
"ts-node": "^10.9.2",
"tsx": "^4.19.3",
"typescript": "^5.7.3",
- "vite": "4.5.5",
+ "vite": "^4.5.13",
"vite-tsconfig-paths": "^5.1.4"
},
"optionalDependencies": {
diff --git a/packages/git-proxy-cli/index.js b/packages/git-proxy-cli/index.js
index b0090a4bf..142a58a33 100755
--- a/packages/git-proxy-cli/index.js
+++ b/packages/git-proxy-cli/index.js
@@ -7,7 +7,8 @@ const util = require('util');
const GIT_PROXY_COOKIE_FILE = 'git-proxy-cookie';
// GitProxy UI HOST and PORT (configurable via environment variable)
-const { GIT_PROXY_UI_HOST: uiHost = 'http://localhost', GIT_PROXY_UI_PORT: uiPort = 8080 } = process.env;
+const { GIT_PROXY_UI_HOST: uiHost = 'http://localhost', GIT_PROXY_UI_PORT: uiPort = 8080 } =
+ process.env;
const baseUrl = `${uiHost}:${uiPort}`;
@@ -306,6 +307,29 @@ async function logout() {
console.log('Logout: OK');
}
+/**
+ * Reloads the GitProxy configuration without restarting the process
+ */
+async function reloadConfig() {
+ if (!fs.existsSync(GIT_PROXY_COOKIE_FILE)) {
+ console.error('Error: Reload config: Authentication required');
+ process.exitCode = 1;
+ return;
+ }
+
+ try {
+ const cookies = JSON.parse(fs.readFileSync(GIT_PROXY_COOKIE_FILE, 'utf8'));
+
+ await axios.post(`${baseUrl}/api/v1/admin/reload-config`, {}, { headers: { Cookie: cookies } });
+
+ console.log('Configuration reloaded successfully');
+ } catch (error) {
+ const errorMessage = `Error: Reload config: '${error.message}'`;
+ process.exitCode = 2;
+ console.error(errorMessage);
+ }
+}
+
// Parsing command line arguments
yargs(hideBin(process.argv)) // eslint-disable-line @typescript-eslint/no-unused-expressions
.command({
@@ -436,6 +460,11 @@ yargs(hideBin(process.argv)) // eslint-disable-line @typescript-eslint/no-unused
rejectGitPush(argv.id);
},
})
+ .command({
+ command: 'reload-config',
+ description: 'Reload GitProxy configuration without restarting',
+ action: reloadConfig,
+ })
.demandCommand(1, 'You need at least one command before moving on')
.strict()
.help().argv;
diff --git a/packages/git-proxy-cli/package.json b/packages/git-proxy-cli/package.json
index baade725c..d8babc8d6 100644
--- a/packages/git-proxy-cli/package.json
+++ b/packages/git-proxy-cli/package.json
@@ -4,7 +4,7 @@
"description": "Command line interface tool for FINOS GitProxy.",
"bin": "./index.js",
"dependencies": {
- "axios": "^1.8.4",
+ "axios": "^1.9.0",
"yargs": "^17.7.2",
"@finos/git-proxy": "file:../.."
},
diff --git a/plugins/git-proxy-plugin-samples/package.json b/plugins/git-proxy-plugin-samples/package.json
index 622b3c3e9..2a9455fcd 100644
--- a/plugins/git-proxy-plugin-samples/package.json
+++ b/plugins/git-proxy-plugin-samples/package.json
@@ -16,6 +16,6 @@
"express": "^4.21.2"
},
"peerDependencies": {
- "@finos/git-proxy": "^1.9.3"
+ "@finos/git-proxy": "^1.11.0"
}
}
diff --git a/proxy.config.json b/proxy.config.json
index fdb32a0d0..9cc017277 100644
--- a/proxy.config.json
+++ b/proxy.config.json
@@ -2,6 +2,10 @@
"proxyUrl": "https://github.com",
"cookieSecret": "cookie secret",
"sessionMaxAgeHours": 12,
+ "rateLimit": {
+ "windowMs": 60000,
+ "limit": 150
+ },
"tempPassword": {
"sendEmail": false,
"emailConfig": {}
@@ -49,6 +53,17 @@
"baseDN": "",
"searchBase": ""
}
+ },
+ {
+ "type": "openidconnect",
+ "enabled": false,
+ "oidcConfig": {
+ "issuer": "",
+ "clientID": "",
+ "clientSecret": "",
+ "callbackURL": "",
+ "scope": ""
+ }
}
],
"api": {
@@ -92,6 +107,39 @@
}
]
},
+ "configurationSources": {
+ "enabled": false,
+ "reloadIntervalSeconds": 60,
+ "merge": false,
+ "sources": [
+ {
+ "type": "file",
+ "enabled": false,
+ "path": "./external-config.json"
+ },
+ {
+ "type": "http",
+ "enabled": false,
+ "url": "http://config-service/git-proxy-config",
+ "headers": {},
+ "auth": {
+ "type": "bearer",
+ "token": ""
+ }
+ },
+ {
+ "type": "git",
+ "enabled": false,
+ "repository": "https://git-server.com/project/git-proxy-config",
+ "branch": "main",
+ "path": "git-proxy/config.json",
+ "auth": {
+ "type": "ssh",
+ "privateKeyPath": "/path/to/.ssh/id_rsa"
+ }
+ }
+ ]
+ },
"domains": {},
"privateOrganizations": [],
"urlShortener": "",
@@ -99,7 +147,7 @@
"csrfProtection": true,
"plugins": [],
"tls": {
- "enabled": true,
+ "enabled": false,
"key": "certs/key.pem",
"cert": "certs/cert.pem"
}
diff --git a/scripts/build-for-publish.sh b/scripts/build-for-publish.sh
new file mode 100755
index 000000000..1c9ac4130
--- /dev/null
+++ b/scripts/build-for-publish.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# This script allows for emitting js and definitions from the typescript into
+# the same import locations as the original files.
+# When we adjust how we import the library we can move to a "dist" folder and
+# explicit "exports".
+
+if [ "${IS_PUBLISHING:-}" != "YES" ]; then
+ echo "This script is intended to prepare the directory for publishing"
+ echo "and replaces files. If you only want to build the UI run \`npm run build-ui\`."
+ echo "Otherwise set IS_PUBLISHING to \"YES\""
+ exit 1
+fi
+
+set -x
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+cd "$REPO_ROOT"
+
+rm -rf dist || true
+tsc --project tsconfig.publish.json
+# replace tsx with node for the new index.js
+sed -ie '1s/tsx/node/' dist/index.js
+# ensure it's executable
+chmod +x dist/index.js
+# move the ts source
+mv src src-old
+# move the built source
+mv dist/src dist/index.js dist/index.d.ts .
+# copy back unchanged ui code
+# could probably drop this as the ui code shouldn't really be imported from
+# the main package but keep for compat until split out.
+mv src-old/ui src/ui
+rm -rf src-old index.ts dist
diff --git a/scripts/undo-build.sh b/scripts/undo-build.sh
new file mode 100755
index 000000000..998123e09
--- /dev/null
+++ b/scripts/undo-build.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+set -euxo pipefail
+
+# Undo what was done by build-for-publish.sh in the event this was ran locally
+
+REPO_ROOT="$(git rev-parse --show-toplevel)"
+cd "$REPO_ROOT"
+
+rm -rf dist index.js index.d.ts || true
+git checkout src index.ts
+git clean -f src
diff --git a/src/config/ConfigLoader.ts b/src/config/ConfigLoader.ts
new file mode 100644
index 000000000..80429e382
--- /dev/null
+++ b/src/config/ConfigLoader.ts
@@ -0,0 +1,419 @@
+import fs from 'fs';
+import path from 'path';
+import axios from 'axios';
+import { execFile } from 'child_process';
+import { promisify } from 'util';
+import EventEmitter from 'events';
+import envPaths from 'env-paths';
+
+const execFileAsync = promisify(execFile);
+
+interface GitAuth {
+ type: 'ssh';
+ privateKeyPath: string;
+}
+
+interface HttpAuth {
+ type: 'bearer';
+ token: string;
+}
+
+interface BaseSource {
+ type: 'file' | 'http' | 'git';
+ enabled: boolean;
+}
+
+interface FileSource extends BaseSource {
+ type: 'file';
+ path: string;
+}
+
+interface HttpSource extends BaseSource {
+ type: 'http';
+ url: string;
+ headers?: Record- + {data.attestation.reviewer.gitAccount} {' '} approved this contribution diff --git a/src/ui/views/PushDetails/components/AttestationView.jsx b/src/ui/views/PushDetails/components/AttestationView.jsx index 70540ca76..9ccbfc8a8 100644 --- a/src/ui/views/PushDetails/components/AttestationView.jsx +++ b/src/ui/views/PushDetails/components/AttestationView.jsx @@ -62,7 +62,7 @@ export default function AttestationView(props) {
Prior to making this code contribution publicly accessible via GitHub, this code
contribution was reviewed and approved by{' '}
-
+
{props.data.reviewer.gitAccount}
. As a reviewer, it was their responsibility to confirm that open sourcing this
@@ -72,7 +72,7 @@ export default function AttestationView(props) {
-
+
{props.data.reviewer.gitAccount}
{' '}
approved this contribution{' '}
diff --git a/src/ui/views/RepoDetails/RepoDetails.jsx b/src/ui/views/RepoDetails/RepoDetails.jsx
index 9c91c1b68..56d80e278 100644
--- a/src/ui/views/RepoDetails/RepoDetails.jsx
+++ b/src/ui/views/RepoDetails/RepoDetails.jsx
@@ -51,7 +51,7 @@ export default function RepoDetails() {
const removeRepository = async (name) => {
await deleteRepo(name);
- navigate('/admin/repo', { replace: true });
+ navigate('/dashboard/repo', { replace: true });
};
const refresh = () => getRepo(setIsLoading, setData, setAuth, setIsError, repoName);
@@ -151,7 +151,7 @@ export default function RepoDetails() {
return (
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Third party APIs
@@ -80,11 +80,11 @@ description: JSON schema reference documentation for GitProxy
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Enforce rules and patterns on commits including e-mail and message
@@ -97,11 +97,11 @@ description: JSON schema reference documentation for GitProxy
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Customisable questions to add to attestation form
@@ -114,11 +114,11 @@ description: JSON schema reference documentation for GitProxy
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Provide domains to use alternative to the defaults
@@ -127,7 +127,88 @@ description: JSON schema reference documentation for GitProxy
- 8. [Optional] Property GitProxy configuration file > privateOrganizations
+ 8. [Optional] Property GitProxy configuration file > rateLimit
+
+
+
+| | |
+| ------------------------- | ----------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Not allowed |
+
+**Description:** API Rate limiting configuration.
+
+
+
+ 8.1. [Required] Property GitProxy configuration file > rateLimit > windowMs
+
+
+
+| | |
+| ------------ | -------- |
+| **Type** | `number` |
+| **Required** | Yes |
+
+**Description:** How long to remember requests for, in milliseconds (default 10 mins).
+
+
+
+ 8.2. [Required] Property GitProxy configuration file > rateLimit > limit
+
+
+
+| | |
+| ------------ | -------- |
+| **Type** | `number` |
+| **Required** | Yes |
+
+**Description:** How many requests to allow (default 150).
+
+
+
+ 9. [Optional] Property GitProxy configuration file > privateOrganizations
@@ -143,7 +224,7 @@ description: JSON schema reference documentation for GitProxy
- 9. [Optional] Property GitProxy configuration file > urlShortener
+ 10. [Optional] Property GitProxy configuration file > urlShortener
@@ -159,7 +240,7 @@ description: JSON schema reference documentation for GitProxy
- 10. [Optional] Property GitProxy configuration file > contactEmail
+ 11. [Optional] Property GitProxy configuration file > contactEmail
@@ -175,7 +256,7 @@ description: JSON schema reference documentation for GitProxy
- 11. [Optional] Property GitProxy configuration file > csrfProtection
+ 12. [Optional] Property GitProxy configuration file > csrfProtection
@@ -191,7 +272,7 @@ description: JSON schema reference documentation for GitProxy
- 12. [Optional] Property GitProxy configuration file > plugins
+ 13. [Optional] Property GitProxy configuration file > plugins
@@ -206,7 +287,7 @@ description: JSON schema reference documentation for GitProxy
| ------------------------------- | ----------- |
| [plugins items](#plugins_items) | - |
-### 12.1. GitProxy configuration file > plugins > plugins items
+### 13.1. GitProxy configuration file > plugins > plugins items
| | |
| ------------ | -------- |
@@ -218,7 +299,7 @@ description: JSON schema reference documentation for GitProxy
- 13. [Optional] Property GitProxy configuration file > authorisedList
+ 14. [Optional] Property GitProxy configuration file > authorisedList
@@ -233,18 +314,18 @@ description: JSON schema reference documentation for GitProxy
| --------------------------------------- | ----------- |
| [authorisedRepo](#authorisedList_items) | - |
-### 13.1. GitProxy configuration file > authorisedList > authorisedRepo
+### 14.1. GitProxy configuration file > authorisedList > authorisedRepo
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
-| **Defined in** | #/definitions/authorisedRepo |
+| | |
+| ------------------------- | ---------------------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
+| **Defined in** | #/definitions/authorisedRepo |
- 13.1.1. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > project
+ 14.1.1. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > project
@@ -258,7 +339,7 @@ description: JSON schema reference documentation for GitProxy
- 13.1.2. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > name
+ 14.1.2. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > name
@@ -272,7 +353,7 @@ description: JSON schema reference documentation for GitProxy
- 13.1.3. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > url
+ 14.1.3. [Required] Property GitProxy configuration file > authorisedList > authorisedList items > url
@@ -289,7 +370,7 @@ description: JSON schema reference documentation for GitProxy
- 14. [Optional] Property GitProxy configuration file > sink
+ 15. [Optional] Property GitProxy configuration file > sink
@@ -304,18 +385,18 @@ description: JSON schema reference documentation for GitProxy
| ------------------------------- | ----------- |
| [database](#sink_items) | - |
-### 14.1. GitProxy configuration file > sink > database
+### 15.1. GitProxy configuration file > sink > database
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
-| **Defined in** | #/definitions/database |
+| | |
+| ------------------------- | ---------------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
+| **Defined in** | #/definitions/database |
- 14.1.1. [Required] Property GitProxy configuration file > sink > sink items > type
+ 15.1.1. [Required] Property GitProxy configuration file > sink > sink items > type
@@ -329,7 +410,7 @@ description: JSON schema reference documentation for GitProxy
- 14.1.2. [Required] Property GitProxy configuration file > sink > sink items > enabled
+ 15.1.2. [Required] Property GitProxy configuration file > sink > sink items > enabled
@@ -343,7 +424,7 @@ description: JSON schema reference documentation for GitProxy
- 14.1.3. [Optional] Property GitProxy configuration file > sink > sink items > connectionString
+ 15.1.3. [Optional] Property GitProxy configuration file > sink > sink items > connectionString
@@ -357,30 +438,30 @@ description: JSON schema reference documentation for GitProxy
- 14.1.4. [Optional] Property GitProxy configuration file > sink > sink items > options
+ 15.1.4. [Optional] Property GitProxy configuration file > sink > sink items > options
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
- 14.1.5. [Optional] Property GitProxy configuration file > sink > sink items > params
+ 15.1.5. [Optional] Property GitProxy configuration file > sink > sink items > params
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
- 15. [Optional] Property GitProxy configuration file > authentication
+ 16. [Optional] Property GitProxy configuration file > authentication
@@ -405,18 +486,18 @@ description: JSON schema reference documentation for GitProxy
| --------------------------------------- | ----------- |
| [authentication](#authentication_items) | - |
-### 15.1. GitProxy configuration file > authentication > authentication
+### 16.1. GitProxy configuration file > authentication > authentication
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
-| **Defined in** | #/definitions/authentication |
+| | |
+| ------------------------- | ---------------------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
+| **Defined in** | #/definitions/authentication |
- 15.1.1. [Required] Property GitProxy configuration file > authentication > authentication items > type
+ 16.1.1. [Required] Property GitProxy configuration file > authentication > authentication items > type
@@ -430,7 +511,7 @@ description: JSON schema reference documentation for GitProxy
- 15.1.2. [Required] Property GitProxy configuration file > authentication > authentication items > enabled
+ 16.1.2. [Required] Property GitProxy configuration file > authentication > authentication items > enabled
@@ -444,15 +525,15 @@ description: JSON schema reference documentation for GitProxy
- 15.1.3. [Optional] Property GitProxy configuration file > authentication > authentication items > options
+ 16.1.3. [Optional] Property GitProxy configuration file > authentication > authentication items > options
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
- 16. [Optional] Property GitProxy configuration file > tempPassword
+ 17. [Optional] Property GitProxy configuration file > tempPassword
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Toggle the generation of temporary password for git-proxy admin user
- 16.1. [Optional] Property GitProxy configuration file > tempPassword > sendEmail
+ 17.1. [Optional] Property GitProxy configuration file > tempPassword > sendEmail
@@ -490,15 +571,15 @@ description: JSON schema reference documentation for GitProxy
- 16.2. [Optional] Property GitProxy configuration file > tempPassword > emailConfig
+ 17.2. [Optional] Property GitProxy configuration file > tempPassword > emailConfig
-| | |
-| ------------------------- | ------------------------------------------------------------------------- |
-| **Type** | `object` |
-| **Required** | No |
-| **Additional properties** | [[Any type: allowed]](# "Additional Properties of any type are allowed.") |
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
**Description:** Generic object to configure nodemailer. For full type information, please see https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nodemailer
@@ -508,5 +589,164 @@ description: JSON schema reference documentation for GitProxy
+ 18. [Optional] Property GitProxy configuration file > tls
+
+
+
+| | |
+| ------------------------- | ---------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | Any type allowed |
+
+**Description:** TLS configuration for secure connections
+
+
+
+ 18.1. [Required] Property GitProxy configuration file > tls > enabled
+
+
+
+| | |
+| ------------ | --------- |
+| **Type** | `boolean` |
+| **Required** | Yes |
+
+
+
+ 19. [Optional] Property GitProxy configuration file > configurationSources
+
+
+
+| | |
+| ------------------------- | ------------------------------------------------------- |
+| **Type** | `object` |
+| **Required** | No |
+| **Additional properties** | [[Not allowed]](# "Additional Properties not allowed.") |
+
+**Description:** Configuration for dynamic loading from external sources
+
+
+
+ 19.1. [Optional] Property configurationSources > enabled
+
+
+
+| | |
+| ------------ | --------- |
+| **Type** | `boolean` |
+| **Required** | No |
+
+**Description:** Enable/disable dynamic configuration loading
+
+
+
+ 19.2. [Optional] Property configurationSources > reloadIntervalSeconds
+
+
+
+| | |
+| ------------ | -------- |
+| **Type** | `number` |
+| **Required** | No |
+
+**Description:** How often to check for configuration updates (in seconds)
+
+
+
+ 19.3. [Optional] Property configurationSources > merge
+
+
+
+| | |
+| ------------ | --------- |
+| **Type** | `boolean` |
+| **Required** | No |
+
+**Description:** When true, merges configurations from all enabled sources. When false, uses the last successful configuration load
+
+
+
+ 19.4. [Optional] Property configurationSources > sources
+
+
+
+| | |
+| ------------ | ------- |
+| **Type** | `array` |
+| **Required** | No |
+
+**Description:** Array of configuration sources to load from
+
+Each item in the array must be an object with the following properties:
+
+- `type`: (Required) Type of configuration source (`"file"`, `"http"`, or `"git"`)
+- `enabled`: (Required) Whether this source is enabled
+- `path`: (Required for `file` type) Path to the configuration file
+- `url`: (Required for `http` type) URL of the configuration endpoint
+- `repository`: (Required for `git` type) Git repository URL
+- `branch`: (Optional for `git` type) Branch to use
+- `path`: (Required for `git` type) Path to configuration file in repository
+- `headers`: (Optional for `http` type) HTTP headers to include
+- `auth`: (Optional) Authentication configuration
+ - For `http` type:
+ - `type`: `"bearer"`
+ - `token`: Bearer token value
+ - For `git` type:
+ - `type`: `"ssh"`
+ - `privateKeyPath`: Path to SSH private key
+
+
+