Skip to content

feat(key on repo url): support git hosts other than GitHub + multiple forks #1043

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 55 commits into
base: main
Choose a base branch
from

Conversation

kriswest
Copy link
Contributor

@kriswest kriswest commented Jun 3, 2025

resolves #950
resolves #511
resolves #66

Refactor (api, proxy & UI) to remove the assumption of GitHub as the git repository host and the use of the repository name field as the id of the repository (as this prevents git-proxy instances from supporting multiple forks of a project or projects from multiple hosts with the same name).

This PR:

  • Replaces the use of the repo name field in the API with the _id field generated by the database adaptors,
    • Using the repository URL as a key does not work well with express routing, but _id does in both mongo and neDb
    • allows names to be repeated (multiple forks or clashing names from different organisations/repository hosts)
    • UI and CLI were updated accordingly
  • Replaces the use of organisation/repoName.git in the proxy URLs with the repository url
  • Disables GitHub specific functionality in the UI if the host is not Github
  • Completes application of Typescript to the database classes
    • Duplicated code reduced
    • A number of minor differences in behaviour (particularly return types) between the DB adaptors were resolved
    • Does NOT refactor all usages of the DB client to use typescript (still many requires to eliminate)
  • Deprecates and ignores the config property proxyUrl as the proxied host(s) are now determined from the configured repositories
  • Expands the tests for proxy routes and the Repo route of the API

To Do:

  • Annotate PR for review
  • Check test coverage
  • Implement additional tests for the proxy and fallback
    • implement tests for new proxy URLs for github.com
    • implement tests for fallback with legacy proxy urls for github.com
    • implement tests for gitlab.com
    • implement tests for non-github/non-gitlab repo
    • implement tests for multiple forks
  • Add support for GitLab API where repo is hosted at GitLab

(contributed as part of a GitLab CoCreate collaboration with help from @StingRayZA)

Copy link

netlify bot commented Jun 3, 2025

Deploy Preview for endearing-brigadeiros-63f9d0 ready!

Name Link
🔨 Latest commit a676c22
🔍 Latest deploy log https://app.netlify.com/projects/endearing-brigadeiros-63f9d0/deploys/686e21f97254ae0008ba55d4
😎 Deploy Preview https://deploy-preview-1043--endearing-brigadeiros-63f9d0.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

codecov bot commented Jun 3, 2025

Codecov Report

Attention: Patch coverage is 83.10811% with 100 lines in your changes missing coverage. Please review.

Project coverage is 80.21%. Comparing base (d48c882) to head (a676c22).

Files with missing lines Patch % Lines
src/db/mongo/repo.ts 37.14% 22 Missing ⚠️
src/service/routes/repo.js 84.90% 16 Missing ⚠️
src/db/mongo/users.ts 37.50% 15 Missing ⚠️
src/db/file/users.ts 65.21% 8 Missing ⚠️
src/proxy/index.ts 80.95% 8 Missing ⚠️
src/db/file/repo.ts 86.36% 3 Missing and 3 partials ⚠️
src/db/index.ts 93.40% 4 Missing and 2 partials ⚠️
src/db/mongo/pushes.ts 55.55% 4 Missing ⚠️
src/proxy/routes/index.ts 94.93% 4 Missing ⚠️
src/proxy/routes/helper.ts 94.23% 3 Missing ⚠️
... and 5 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1043      +/-   ##
==========================================
+ Coverage   76.91%   80.21%   +3.29%     
==========================================
  Files          55       62       +7     
  Lines        2270     2608     +338     
  Branches      255      308      +53     
==========================================
+ Hits         1746     2092     +346     
+ Misses        494      469      -25     
- Partials       30       47      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@sam-holmes2 sam-holmes2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after an initial scan through :) thanks for your contribution!

@@ -578,20 +578,24 @@ export default function Repositories(props) {
getGitHubRepository();
}, [props.data.project, props.data.name]);

// TODO add support for GitLab API: https://docs.gitlab.com/api/projects/#get-a-single-project
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagging for awareness

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had some input from @StingRayZA @ Gitlab on this and will update the PR acordingly. after I've dealt with the test mentioned below.

@kriswest
Copy link
Contributor Author

kriswest commented Jun 5, 2025

Picked up a couple of test failures after merging main - will resolve (and start working on the additional tests needed).

Copy link
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through the approval/rejection flows with a pre-existing repo, and things work well!

There is an issue with backwards compatibility with older, invalid databases from previous versions of GitProxy (unique URL enforcement with repos). This may also cause issues with the other files (pushes, users).

I also tested the Add Repo flow which caused my server to crash, maybe because of something wrong on my end (invalid input maybe?).

const { proxy } = require('../index');

// 2. Stop existing services
await proxy.stop();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got an error here when trying to add a new GitHub repository:

[0] API request to proxy repository https://github.com/jescalada/open-webui.git is for a new origin: true,
[0]     existing origin list was: ["github.com"]
[0] creating new repo {"project":"jescalada","name":"open-webui","url":"https://github.com/jescalada/open-webui.git","maxUser":1,"users":{"canPush":[],"canAuthorise":[]}}
[0] Restarting the proxy to handle an additional origin
[0] Repository creation failed due to error:  Cannot read properties of undefined (reading 'stop')
[0] node:_http_outgoing:655
[0]     throw new ERR_HTTP_HEADERS_SENT('set');
[0]           ^
[0] 
[0] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[0]     at ServerResponse.setHeader (node:_http_outgoing:655:11)
[0]     at ServerResponse.header (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/express/lib/response.js:794:10)
[0]     at ServerResponse.send (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/express/lib/response.js:174:12)
[0]     at /home/juan/Desktop/Juan/Projects/git-proxy/src/service/routes/repo.js:168:13
[0]     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
[0]   code: 'ERR_HTTP_HEADERS_SENT'
[0] }
[0] 
[0] Node.js v20.19.2
[0] npm run server exited with code 1

Interestingly, restarting the server does show the newly added repo in the dashboard:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thats got to be at least two errors in the proxy restart code - its made all the DB changes by that point and it just needs to restart the proxy if we have a new host to handle. In your example, it doesn't actually need to do that as the list of proxied hosts hasn't changed (you've just added another repo at a particular host). I'll need to take another look at that I guess!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had a go at the relevant fixes, but can't test properly until after OSFF. If you end up giving it a go let me know @jescalada!

BTW I'm tempted to merge your proxy route test PR into this and update 9as the routes change slightly). It looks like you got a handle on testing the API routes with Chai http (although I haven't run them and did see your comment about issues). I was planning to try and test the getRouter() and its output, but your tests might be a better approach, as long as we add one that checks routes after adding a new repository host/origin and triggering a restart of the proxy.

Thoughts?

Copy link
Contributor

@jescalada jescalada Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'd be super helpful if you don't mind the extra work with the tests! I was actually planning on covering any missing/extra code on a follow-up PR to get the overall coverage to 80%. Maybe we could go ahead and merge this as-is so you don't have to keep maintaining the PR?

@kriswest

This comment was marked as resolved.

@@ -47,15 +46,6 @@ let _config = { ...defaultSettings, ...(_userSettings || {}) } as Configuration;
// Create config loader instance
const configLoader = new ConfigLoader(_config);

// Get configured proxy URL
export const getProxyUrl = () => {
if (_userSettings !== null && _userSettings.proxyUrl) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing this function entirely, wouldn't it be useful to emit a warning indicating that this field is deprecated? It can be ignored from use but if it's present in _userSettings, we want to indicate that a config change is needed.

export const getTLSKeyPemPath = () => {
if (_userSettings && _userSettings.sslKeyPemPath) {
console.log(
'Warning: sslKeyPemPath setting is replaced with tls.key setting in proxy.config.json & will be deprecated in a future release',
);
_tlsKeyPemPath = _userSettings.sslKeyPemPath;
}
if (_userSettings?.tls && _userSettings?.tls?.key) {
_tlsKeyPemPath = _userSettings.tls.key;
}
return _tlsKeyPemPath;
};

Copy link
Contributor Author

@kriswest kriswest Jul 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! As the function is no longer called, that would need to be done on load

https://github.com/finos/git-proxy/pull/1043/files#diff-198a1431d7c5e26ea78bc6e54b34b54e6f8ab342dd48ea11013877e8466a87c5R19-R25

I suppose we could suck up the warnings and copies for handling sslKeyPemPath and sslCertPemPath into the same spot if you thought it worth while.

@jescalada
Copy link
Contributor

I can release the unique constraint on the index to avoid this - however, I put it in to catch invalid data as, like the use of the repository name as an ID, it will result in the selection of the wrong repo project at times (although in this case the multiple records would have to be the same repo) and I thought it better for tests to fail etc. if data wasn't cleaned up from a previous run. Where do you think we should go with this @jescalada - an automated migration seems difficult as you'd just have to delete or programmatically edit one of the duplicate records...

I think catching and displaying a simple error message with the invalid entry/entries could be enough - so that the GitProxy administrator can quickly identify the issue and fix it manually. Thankfully, the error seems to occur on backend (db) startup, so end users wouldn't really have the app suddenly blowing up.

kriswest and others added 20 commits July 3, 2025 10:17
Signed-off-by: Raimund Hook <rhook@gitlab.com>
Signed-off-by: Raimund Hook <rhook@gitlab.com>
Signed-off-by: Raimund Hook <rhook@gitlab.com>
Typescript wasn't working on the DB classes due to their dependency imports with require.
@kriswest kriswest force-pushed the 950-key-on-repo-urls branch from 802b61b to 92b801b Compare July 4, 2025 16:26
@kriswest kriswest force-pushed the 950-key-on-repo-urls branch from 5502cdb to e5cb9c9 Compare July 4, 2025 16:51
@kriswest kriswest force-pushed the 950-key-on-repo-urls branch from c2aedf0 to fe934df Compare July 4, 2025 17:44
@kriswest kriswest force-pushed the 950-key-on-repo-urls branch from 8358124 to e059206 Compare July 4, 2025 17:57
@kriswest
Copy link
Contributor Author

kriswest commented Jul 8, 2025

I've implemented tests covering adding and removing an alternative origin (gitlab), although I need to select a smaller repo for the test (than Gitlab itself). In doing so I've finally dealt with the issue with restarting the proxy.

@jescalada I had originally copied what you did in config loading - I don't think that approach is working. When you require the proxy and call stop() its creating another instance, rather than applying that to the running instance. I tried applying a singleton pattern and messing with import/require but I get a separate instance every time. In the end I've had to have the API service's start() function take the proxy as an argument so it has a reference to the right instance to restart. That approach won't quite work for the config as it would create a circular dependency. Rather I think you'll probably have to expose the 'configurationChanged event and have the proxy register a handler with the config so that it can restart itself instead.

I have some additional cleanup still to do and gitlab API calls to work into the UI, but otherwise I think this is working now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants