Skip to content

Commit 686fe63

Browse files
Add gitlab support
1 parent 7d987b3 commit 686fe63

15 files changed

+701
-87
lines changed

README.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,10 @@ docker-compose run -- database add-directory <DIRECTORY> [PREFIX]
191191
# You need to set CRATESFYI_GITHUB_USERNAME, CRATESFYI_GITHUB_ACCESSTOKEN
192192
# environment variables in order to run this command.
193193
# You can set this environment variables in ~/.cratesfyi.env file.
194-
docker-compose run -- database update-github-fields
194+
cargo run -- database update-github-fields
195+
# Updates github stats for crates.
196+
# You need to set CRATESFYI_GITLAB_ACCESSTOKEN environment variable.
197+
cargo run -- database update-gitlab-fields
195198
```
196199

197200
If you want to explore or edit database manually, you can connect to the database

src/bin/cratesfyi.rs

+18
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,12 @@ enum DatabaseSubcommand {
377377
/// Backfill GitHub stats for crates.
378378
BackfillGithubStats,
379379

380+
/// Updates gitlab stats for crates.
381+
UpdateGitlabFields,
382+
383+
/// Backfill Gitlab stats for crates.
384+
BackfillGitlabStats,
385+
380386
/// Updates info for a crate from the registry's API
381387
UpdateCrateRegistryFields {
382388
#[structopt(name = "CRATE")]
@@ -436,6 +442,18 @@ impl DatabaseSubcommand {
436442
.backfill_repositories()?;
437443
}
438444

445+
Self::UpdateGitlabFields => {
446+
docs_rs::utils::GitlabUpdater::new(ctx.config()?, ctx.pool()?)?
447+
.ok_or_else(|| failure::format_err!("missing Gitlab token"))?
448+
.update_all_crates()?;
449+
}
450+
451+
Self::BackfillGitlabStats => {
452+
docs_rs::utils::GitlabUpdater::new(ctx.config()?, ctx.pool()?)?
453+
.ok_or_else(|| failure::format_err!("missing Gitlab token"))?
454+
.backfill_repositories()?;
455+
}
456+
439457
Self::UpdateCrateRegistryFields { name } => {
440458
let index = ctx.index()?;
441459

src/config.rs

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ pub struct Config {
3030
pub(crate) github_accesstoken: Option<String>,
3131
pub(crate) github_updater_min_rate_limit: u32,
3232

33+
// Gitlab authentication
34+
pub(crate) gitlab_accesstoken: Option<String>,
35+
pub(crate) gitlab_updater_min_rate_limit: u32,
36+
3337
// Max size of the files served by the docs.rs frontend
3438
pub(crate) max_file_size: usize,
3539
pub(crate) max_file_size_html: usize,
@@ -77,6 +81,9 @@ impl Config {
7781
github_accesstoken: maybe_env("CRATESFYI_GITHUB_ACCESSTOKEN")?,
7882
github_updater_min_rate_limit: env("DOCSRS_GITHUB_UPDATER_MIN_RATE_LIMIT", 2500)?,
7983

84+
gitlab_accesstoken: maybe_env("CRATESFYI_GITLAB_ACCESSTOKEN")?,
85+
gitlab_updater_min_rate_limit: env("DOCSRS_GITLAB_UPDATER_MIN_RATE_LIMIT", 2500)?,
86+
8087
max_file_size: env("DOCSRS_MAX_FILE_SIZE", 50 * 1024 * 1024)?,
8188
max_file_size_html: env("DOCSRS_MAX_FILE_SIZE_HTML", 50 * 1024 * 1024)?,
8289
// LOL HTML only uses as much memory as the size of the start tag!

src/db/add_package.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub(crate) fn add_package_into_database(
3737
has_docs: bool,
3838
has_examples: bool,
3939
compression_algorithms: std::collections::HashSet<CompressionAlgorithm>,
40-
github_repo: Option<String>,
40+
repository_id: Option<i32>,
4141
) -> Result<i32> {
4242
debug!("Adding package into database");
4343
let crate_id = initialize_package_in_database(conn, metadata_pkg)?;
@@ -55,7 +55,8 @@ pub(crate) fn add_package_into_database(
5555
homepage_url, description, description_long, readme,
5656
authors, keywords, have_examples, downloads, files,
5757
doc_targets, is_library, doc_rustc_version,
58-
documentation_url, default_target, features, github_repo
58+
documentation_url, default_target, features,
59+
repository
5960
)
6061
VALUES (
6162
$1, $2, $3, $4, $5, $6, $7, $8, $9,
@@ -87,7 +88,7 @@ pub(crate) fn add_package_into_database(
8788
documentation_url = $24,
8889
default_target = $25,
8990
features = $26,
90-
github_repo = $27
91+
repository = $27
9192
RETURNING id",
9293
&[
9394
&crate_id,
@@ -116,7 +117,7 @@ pub(crate) fn add_package_into_database(
116117
&metadata_pkg.documentation,
117118
&default_target,
118119
&features,
119-
&github_repo,
120+
&repository_id,
120121
],
121122
)?;
122123

src/db/migrate.rs

+82
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,88 @@ pub fn migrate(version: Option<Version>, conn: &mut Client) -> CratesfyiResult<(
618618
DROP INDEX github_repos_stars_idx;
619619
",
620620
),
621+
migration!(
622+
context,
623+
27,
624+
// description
625+
"Add gitlab handling: creation of the new repositories table which replaces and extend \
626+
github_repos",
627+
// upgrade query
628+
"
629+
CREATE TABLE repositories (
630+
id SERIAL PRIMARY KEY,
631+
host VARCHAR NOT NULL,
632+
host_id VARCHAR NOT NULL,
633+
name VARCHAR NOT NULL,
634+
description VARCHAR,
635+
last_commit TIMESTAMPTZ,
636+
stars INT NOT NULL,
637+
forks INT NOT NULL,
638+
issues INT NOT NULL,
639+
updated_at TIMESTAMPTZ NOT NULL,
640+
UNIQUE (host, host_id)
641+
);
642+
643+
ALTER TABLE releases ADD COLUMN repository INTEGER
644+
REFERENCES repositories(id) ON DELETE SET NULL;
645+
646+
INSERT INTO repositories(host, host_id, name, description, last_commit, stars, forks, issues, updated_at)
647+
SELECT 'github', id, name, description, last_commit, stars, forks, issues, updated_at
648+
FROM github_repos;
649+
650+
UPDATE releases
651+
SET repository = repositories.id
652+
FROM repositories
653+
WHERE releases.github_repo IS NOT NULL AND repositories.host_id = releases.github_repo;
654+
655+
DROP INDEX releases_github_repo_idx;
656+
DROP INDEX github_repos_stars_idx;
657+
658+
CREATE INDEX releases_github_repo_idx ON releases(repository);
659+
CREATE INDEX github_repos_stars_idx ON repositories(stars DESC);
660+
661+
ALTER TABLE releases
662+
DROP COLUMN github_repo;
663+
664+
DROP TABLE github_repos;
665+
",
666+
// downgrade query
667+
"
668+
CREATE TABLE github_repos (
669+
id VARCHAR PRIMARY KEY NOT NULL,
670+
name VARCHAR NOT NULL,
671+
description VARCHAR,
672+
last_commit TIMESTAMPTZ,
673+
stars INT NOT NULL,
674+
forks INT NOT NULL,
675+
issues INT NOT NULL,
676+
updated_at TIMESTAMPTZ NOT NULL
677+
);
678+
679+
ALTER TABLE releases ADD COLUMN github_repo VARCHAR
680+
REFERENCES github_repos(id) ON DELETE SET NULL;
681+
682+
INSERT INTO github_repos(id, name, description, last_commit, stars, forks, issues, updated_at)
683+
SELECT host_id, name, description, last_commit, stars, forks, issues, updated_at
684+
FROM repositories WHERE repositories.host = 'github';
685+
686+
UPDATE releases
687+
SET github_repo = repositories.host_id
688+
FROM repositories
689+
WHERE repositories.host_id = releases.github_repo AND releases.repository IS NOT NULL AND repositories.host = 'github';
690+
691+
DROP INDEX releases_github_repo_idx;
692+
DROP INDEX github_repos_stars_idx;
693+
694+
CREATE INDEX releases_github_repo_idx ON releases (github_repo);
695+
CREATE INDEX github_repos_stars_idx ON github_repos(stars DESC);
696+
697+
ALTER TABLE releases
698+
DROP COLUMN repository;
699+
700+
DROP TABLE repository;
701+
"
702+
),
621703
];
622704

623705
for migration in migrations {

src/docbuilder/rustwide_builder.rs

+37-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use crate::docbuilder::{crates::crates_from_path, Limits};
77
use crate::error::Result;
88
use crate::index::api::ReleaseData;
99
use crate::storage::CompressionAlgorithms;
10-
use crate::utils::{copy_doc_dir, parse_rustc_version, CargoMetadata, GithubUpdater};
10+
use crate::utils::{
11+
copy_doc_dir, parse_rustc_version, CargoMetadata, GithubUpdater, GitlabUpdater,
12+
};
1113
use crate::{db::blacklist::is_blacklisted, utils::MetadataPackage};
1214
use crate::{Config, Context, Index, Metrics, Storage};
1315
use docsrs_metadata::{Metadata, DEFAULT_TARGETS, HOST_TARGET};
@@ -393,7 +395,10 @@ impl RustwideBuilder {
393395
};
394396

395397
let cargo_metadata = res.cargo_metadata.root();
396-
let github_repo = self.get_github_repo(&mut conn, cargo_metadata)?;
398+
let repository = match self.get_github_repo(&mut conn, cargo_metadata)? {
399+
Some(r) => Some(r),
400+
None => self.get_gitlab_repo(&mut conn, cargo_metadata)?,
401+
};
397402

398403
let release_id = add_package_into_database(
399404
&mut conn,
@@ -407,7 +412,7 @@ impl RustwideBuilder {
407412
has_docs,
408413
has_examples,
409414
algs,
410-
github_repo,
415+
repository,
411416
)?;
412417

413418
if let Some(doc_coverage) = res.doc_coverage {
@@ -678,7 +683,7 @@ impl RustwideBuilder {
678683
&self,
679684
conn: &mut Client,
680685
metadata: &MetadataPackage,
681-
) -> Result<Option<String>> {
686+
) -> Result<Option<i32>> {
682687
let updater = match GithubUpdater::new(self.config.clone(), self.db.clone())? {
683688
Some(updater) => updater,
684689
None => {
@@ -701,6 +706,34 @@ impl RustwideBuilder {
701706
}
702707
}
703708
}
709+
710+
fn get_gitlab_repo(
711+
&self,
712+
conn: &mut Client,
713+
metadata: &MetadataPackage,
714+
) -> Result<Option<i32>> {
715+
let updater = match GitlabUpdater::new(self.config.clone(), self.db.clone())? {
716+
Some(updater) => updater,
717+
None => {
718+
warn!("did not collect Gitlab stats as no token was provided");
719+
return Ok(None);
720+
}
721+
};
722+
let repo = match &metadata.repository {
723+
Some(url) => url,
724+
None => {
725+
debug!("did not collect Gitlab stats as no repository URL was present");
726+
return Ok(None);
727+
}
728+
};
729+
match updater.load_repository(conn, repo) {
730+
Ok(repo) => Ok(repo),
731+
Err(err) => {
732+
warn!("failed to collect Gitlab stats: {}", err);
733+
Ok(None)
734+
}
735+
}
736+
}
704737
}
705738

706739
struct FullBuildResult {

src/test/fakes.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl<'a> FakeRelease<'a> {
316316
}
317317
}
318318

319-
let github_repo = match self.github_stats {
319+
let repository = match self.github_stats {
320320
Some(stats) => Some(stats.create(&mut self.db.conn())?),
321321
None => None,
322322
};
@@ -338,7 +338,7 @@ impl<'a> FakeRelease<'a> {
338338
self.has_docs,
339339
self.has_examples,
340340
algs,
341-
github_repo,
341+
repository,
342342
)?;
343343
crate::db::update_crate_data_in_database(
344344
&mut db.conn(),
@@ -366,13 +366,13 @@ struct FakeGithubStats {
366366
impl FakeGithubStats {
367367
fn create(&self, conn: &mut Client) -> Result<String, Error> {
368368
let existing_count: i64 = conn
369-
.query_one("SELECT COUNT(*) FROM github_repos;", &[])?
369+
.query_one("SELECT COUNT(*) FROM repositories;", &[])?
370370
.get(0);
371371
let id = base64::encode(format!("FAKE ID {}", existing_count));
372372

373373
conn.execute(
374-
"INSERT INTO github_repos (id, name, description, last_commit, stars, forks, issues, updated_at)
375-
VALUES ($1, $2, 'Fake description!', NOW(), $3, $4, $5, NOW());",
374+
"INSERT INTO repositories (host, host_id, name, description, last_commit, stars, forks, issues, updated_at)
375+
VALUES ('github', $1, $2, 'Fake description!', NOW(), $3, $4, $5, NOW());",
376376
&[&id, &self.repo, &self.stars, &self.forks, &self.issues],
377377
)?;
378378

src/utils/daemon.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This daemon will start web server, track new packages and build them
44
55
use crate::{
6-
utils::{queue_builder, update_release_activity, GithubUpdater},
6+
utils::{queue_builder, update_release_activity, GithubUpdater, GitlabUpdater},
77
Context, DocBuilder, RustwideBuilder,
88
};
99
use chrono::{Timelike, Utc};
@@ -93,7 +93,7 @@ pub fn start_daemon(context: &dyn Context, enable_registry_watcher: bool) -> Res
9393
},
9494
)?;
9595

96-
if let Some(github_updater) = GithubUpdater::new(config, context.pool()?)? {
96+
if let Some(github_updater) = GithubUpdater::new(config.clone(), context.pool()?)? {
9797
cron(
9898
"github stats updater",
9999
Duration::from_secs(60 * 60),
@@ -106,6 +106,19 @@ pub fn start_daemon(context: &dyn Context, enable_registry_watcher: bool) -> Res
106106
log::warn!("GitHub stats updater not started as no token was provided");
107107
}
108108

109+
if let Some(gitlab_updater) = GitlabUpdater::new(config, context.pool()?)? {
110+
cron(
111+
"gitlab stats updater",
112+
Duration::from_secs(60 * 60),
113+
move || {
114+
gitlab_updater.update_all_crates()?;
115+
Ok(())
116+
},
117+
)?;
118+
} else {
119+
log::warn!("Gitlab stats updater not started as no token was provided");
120+
}
121+
109122
// Never returns; `server` blocks indefinitely when dropped
110123
// NOTE: if a failure occurred earlier in `start_daemon`, the server will _not_ be joined -
111124
// instead it will get killed when the process exits.

0 commit comments

Comments
 (0)