-
-
Notifications
You must be signed in to change notification settings - Fork 345
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
GitLab kref #3661
GitLab kref #3661
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using System; | ||
using System.Linq; | ||
using System.Collections.Generic; | ||
|
||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
using CKAN.NetKAN.Services; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Provides convenient access to the GitLab API | ||
/// https://docs.gitlab.com/ee/api/ | ||
/// </summary> | ||
internal sealed class GitlabApi : IGitlabApi | ||
{ | ||
/// <summary> | ||
/// Initialize the API object | ||
/// </summary> | ||
/// <param name="http">HTTP service for getting URLs</param> | ||
/// <param name="token">GitLab API token</param> | ||
public GitlabApi(IHttpService http, string token = null) | ||
{ | ||
this.http = http; | ||
this.token = token; | ||
} | ||
|
||
/// <summary> | ||
/// Retrieve info about a GitLab project from the API | ||
/// </summary> | ||
/// <param name="reference">Specification of which project to retrieve</param> | ||
/// <returns>A project object</returns> | ||
public GitlabProject GetProject(GitlabRef reference) | ||
{ | ||
// https://docs.gitlab.com/ee/api/projects | ||
return JsonConvert.DeserializeObject<GitlabProject>( | ||
http.DownloadText( | ||
new Uri(apiBase, $"{reference.Account}%2F{reference.Project}"), | ||
token, null)); | ||
} | ||
|
||
/// <summary> | ||
/// Retrieve info about a GitLab project's releases from the API | ||
/// </summary> | ||
/// <param name="reference">Specification of which project's releases to retrieve</param> | ||
/// <returns>Sequence of release objects from the API</returns> | ||
public IEnumerable<GitlabRelease> GetAllReleases(GitlabRef reference) | ||
{ | ||
// https://docs.gitlab.com/ee/api/releases/ | ||
return JArray.Parse( | ||
http.DownloadText( | ||
new Uri(apiBase, $"{reference.Account}%2F{reference.Project}/releases"), | ||
token, null)) | ||
.Select(releaseJson => releaseJson.ToObject<GitlabRelease>()); | ||
} | ||
|
||
private IHttpService http; | ||
private string token; | ||
|
||
private static readonly Uri apiBase = new Uri("https://gitlab.com/api/v4/projects/"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Represents the x_netkan_gitlab object from a netkan | ||
/// </summary> | ||
internal sealed class GitlabOptions | ||
{ | ||
/// <summary> | ||
/// True to use source ZIP for a release. | ||
/// Note that this MUST be true because GitLab only provides source ZIPs! | ||
/// If they add other assets in the future, this requirement can be relaxed. | ||
/// </summary> | ||
[JsonProperty("use_source_archive")] | ||
public readonly bool UseSourceArchive = false; | ||
Comment on lines
+10
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be misunderstanding the help text here, it says MUST be true and we're setting it to false? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it's kind-of supposed to be weird. The idea is to force all GitLab netkans to add the below metadata: x_netkan_gitlab:
use_source_archive: true ... until we can add the option of removing that. The Let's look at this repo's releases to illustrate why: https://gitlab.com/djdisodo/kspremote/-/releases The https://gitlab.com/api/v4/projects/djdisodo%2Fkspremote/releases [
{
"name": "release-1.1.0",
"tag_name": "release-1.1.0",
"description": "[app-debug.apk](/uploads/4ae81fe659c9d621ee64099522324c31/app-debug.apk)",
"created_at": "2020-05-01T10:40:09.568Z",
"released_at": "2020-05-01T10:40:09.567Z",
"upcoming_release": false,
"author": {
"id": 2563867,
"username": "djdisodo",
"name": "lee jisoo",
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/ed5d23ffb1070c0ed33cc8c6dead8d11?s=80&d=identicon",
"web_url": "https://gitlab.com/djdisodo"
},
"commit": {
"id": "a4a7d1112b2953dbcfa113fa9c68c8aebd3f751d",
"short_id": "a4a7d111",
"created_at": "2020-05-01T19:31:16.000+09:00",
"parent_ids": [
"66388dcd8b8881107b50e13545bfa6b4461b209a",
"6359357ea2f3d18157bf04b18a63d6988d971616"
],
"title": "Merge branch 'master' of https://gitlab.com/djdisodo/kspremote",
"message": "Merge branch 'master' of https://gitlab.com/djdisodo/kspremote\n",
"author_name": "djdisodo",
"author_email": "[email protected]",
"authored_date": "2020-05-01T19:31:16.000+09:00",
"committer_name": "djdisodo",
"committer_email": "[email protected]",
"committed_date": "2020-05-01T19:31:16.000+09:00",
"trailers": {},
"web_url": "https://gitlab.com/djdisodo/kspremote/-/commit/a4a7d1112b2953dbcfa113fa9c68c8aebd3f751d"
},
"commit_path": "/djdisodo/kspremote/-/commit/a4a7d1112b2953dbcfa113fa9c68c8aebd3f751d",
"tag_path": "/djdisodo/kspremote/-/tags/release-1.1.0",
"assets": {
"count": 4,
"sources": [
{
"format": "zip",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-1.1.0/kspremote-release-1.1.0.zip"
},
{
"format": "tar.gz",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-1.1.0/kspremote-release-1.1.0.tar.gz"
},
{
"format": "tar.bz2",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-1.1.0/kspremote-release-1.1.0.tar.bz2"
},
{
"format": "tar",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-1.1.0/kspremote-release-1.1.0.tar"
}
],
"links": []
},
"evidences": [],
"_links": {
"self": "https://gitlab.com/djdisodo/kspremote/-/releases/release-1.1.0"
}
},
{
"name": "release-beta4",
"tag_name": "release-beta4",
"description": "[app-debug.apk](/uploads/5db2c5ac589d55abd37c4dcd18942f6e/app-debug.apk)",
"created_at": "2020-02-15T17:13:28.144Z",
"released_at": "2020-02-15T17:13:28.134Z",
"upcoming_release": false,
"author": {
"id": 2563867,
"username": "djdisodo",
"name": "lee jisoo",
"state": "active",
"avatar_url": "https://secure.gravatar.com/avatar/ed5d23ffb1070c0ed33cc8c6dead8d11?s=80&d=identicon",
"web_url": "https://gitlab.com/djdisodo"
},
"commit": {
"id": "6359357ea2f3d18157bf04b18a63d6988d971616",
"short_id": "6359357e",
"created_at": "2020-02-15T16:51:00.000+00:00",
"parent_ids": [
"af7fa415f0fd741c8ab5894dec7f8b9d09e5d746"
],
"title": "Update README.md",
"message": "Update README.md",
"author_name": "lee jisoo",
"author_email": "[email protected]",
"authored_date": "2020-02-15T16:51:00.000+00:00",
"committer_name": "lee jisoo",
"committer_email": "[email protected]",
"committed_date": "2020-02-15T16:51:00.000+00:00",
"trailers": {},
"web_url": "https://gitlab.com/djdisodo/kspremote/-/commit/6359357ea2f3d18157bf04b18a63d6988d971616"
},
"commit_path": "/djdisodo/kspremote/-/commit/6359357ea2f3d18157bf04b18a63d6988d971616",
"tag_path": "/djdisodo/kspremote/-/tags/release-beta4",
"assets": {
"count": 4,
"sources": [
{
"format": "zip",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-beta4/kspremote-release-beta4.zip"
},
{
"format": "tar.gz",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-beta4/kspremote-release-beta4.tar.gz"
},
{
"format": "tar.bz2",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-beta4/kspremote-release-beta4.tar.bz2"
},
{
"format": "tar",
"url": "https://gitlab.com/djdisodo/kspremote/-/archive/release-beta4/kspremote-release-beta4.tar"
}
],
"links": []
},
"evidences": [],
"_links": {
"self": "https://gitlab.com/djdisodo/kspremote/-/releases/release-beta4"
}
}
] If we want to index a mod from there using the API, we have 4 choices: source zip, source tar.gz, source tar.bz2, and source tar. That's why it says in various comments here that we can only support source archives for GitLab (and why we couldn't index that specific mod, even after this PR). The hope is that someday GitLab will improve their API to support non-source assets, and if/when that happens, we can remove this limitation. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Newtonsoft.Json; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Represents a project from the GitLab API | ||
/// </summary> | ||
public sealed class GitlabProject | ||
{ | ||
[JsonProperty("name")] | ||
public readonly string Name; | ||
|
||
[JsonProperty("description")] | ||
public readonly string Description; | ||
|
||
[JsonProperty("web_url")] | ||
public readonly string WebURL; | ||
|
||
[JsonProperty("issues_enabled")] | ||
public readonly bool IssuesEnabled; | ||
|
||
[JsonProperty("readme_url")] | ||
public readonly string ReadMeURL; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System.Text.RegularExpressions; | ||
|
||
using CKAN.NetKAN.Model; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Represents a GitLab $kref | ||
/// </summary> | ||
internal sealed class GitlabRef : RemoteRef | ||
{ | ||
/// <summary> | ||
/// Initialize the GitLab reference | ||
/// </summary> | ||
/// <param name="reference">The base $kref object from a netkan</param> | ||
public GitlabRef(RemoteRef reference) | ||
: base(reference) | ||
{ | ||
var match = Pattern.Match(reference.Id); | ||
if (match.Success) | ||
{ | ||
Account = match.Groups["account"].Value; | ||
Project = match.Groups["project"].Value; | ||
} | ||
else | ||
{ | ||
throw new Kraken(string.Format(@"Could not parse reference: ""{0}""", reference)); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The first part of the "account/project" path from GitLab | ||
/// </summary> | ||
public readonly string Account; | ||
/// <summary> | ||
/// The second part of the "account/project" path from GitLab | ||
/// </summary> | ||
public readonly string Project; | ||
|
||
private static readonly Regex Pattern = new Regex( | ||
@"^(?<account>[^/]+)/(?<project>[^/]+)$", | ||
RegexOptions.Compiled); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
using Newtonsoft.Json; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Represents a release from the GitLab API | ||
/// </summary> | ||
internal sealed class GitlabRelease | ||
{ | ||
[JsonProperty("tag_name")] | ||
public readonly string TagName; | ||
|
||
[JsonProperty("author")] | ||
public readonly GitlabReleaseAuthor Author = new GitlabReleaseAuthor(); | ||
|
||
[JsonProperty("released_at")] | ||
public readonly DateTime ReleasedAt; | ||
|
||
[JsonProperty("assets")] | ||
public readonly GitlabReleaseAssets Assets = new GitlabReleaseAssets(); | ||
} | ||
|
||
/// <summary> | ||
/// Represents an author from the GitLab API | ||
/// </summary> | ||
internal sealed class GitlabReleaseAuthor | ||
{ | ||
[JsonProperty("name")] | ||
public readonly string Name; | ||
} | ||
|
||
/// <summary> | ||
/// Represents an assets object from the GitLab API | ||
/// </summary> | ||
internal sealed class GitlabReleaseAssets | ||
{ | ||
[JsonProperty("sources")] | ||
public readonly List<GitlabReleaseAssetSource> Sources = new List<GitlabReleaseAssetSource>(); | ||
} | ||
|
||
/// <summary> | ||
/// Represents an assets source object from the GitLab API | ||
/// </summary> | ||
internal sealed class GitlabReleaseAssetSource | ||
{ | ||
[JsonProperty("format")] | ||
public readonly string Format; | ||
|
||
[JsonProperty("url")] | ||
public readonly string URL; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System.Collections.Generic; | ||
|
||
namespace CKAN.NetKAN.Sources.Gitlab | ||
{ | ||
/// <summary> | ||
/// Interface for classes providing access to the GitLab API | ||
/// Allows mocking up in tests | ||
/// </summary> | ||
internal interface IGitlabApi | ||
{ | ||
/// <summary> | ||
/// Retrieve info about a GitLab project from the API | ||
/// </summary> | ||
/// <param name="reference">Specification of which project to retrieve</param> | ||
/// <returns>A project object</returns> | ||
GitlabProject GetProject(GitlabRef reference); | ||
|
||
/// <summary> | ||
/// Retrieve info about a GitLab project's releases from the API | ||
/// </summary> | ||
/// <param name="reference">Specification of which project's releases to retrieve</param> | ||
/// <returns>Sequence of release objects from the API</returns> | ||
IEnumerable<GitlabRelease> GetAllReleases(GitlabRef reference); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to to setup a gitlab account for the indexer? Or will we get by until we reach their API limit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will want to create a GitLab token for this just for completeness/robustness, but I tested it without a token and it still worked. If I'm reading this table correctly, a token boosts the rate limiting from 500 to 2000 requests per minute:
https://docs.gitlab.com/ee/user/gitlab_com/index.html#gitlabcom-specific-rate-limits