@@ -1,233 +1,22 @@
-use std::sync::{Arc, OnceLock};
+use std::sync::Arc;
use axum::{
Extension, Json, Router,
- extract::{self, Query},
+ extract::{self},
routing::get,
};
-use chrono::{NaiveDateTime, SecondsFormat};
-use serde::{Deserialize, Serialize};
+use serde::Deserialize;
-use crate::db::ContributorSelector;
use crate::{AppState, Result};
pub fn router() -> Router {
- Router::new()
- .route("/contributors", get(get_contributors).post(add_contributor))
- .route("/contributor", get(check_is_contributor))
+ Router::new().route("/contributors", get(get_contributors).post(add_contributor))
}
async fn get_contributors(Extension(app): Extension<Arc<AppState>>) -> Result<Json<Vec<String>>> {
Ok(Json(app.db.get_contributors().await?))
}
-#[derive(Debug, Deserialize)]
-struct CheckIsContributorParams {
- github_user_id: Option<i32>,
- github_login: Option<String>,
-}
-
-impl CheckIsContributorParams {
- fn into_contributor_selector(self) -> Result<ContributorSelector> {
- if let Some(github_user_id) = self.github_user_id {
- return Ok(ContributorSelector::GitHubUserId { github_user_id });
- }
-
- if let Some(github_login) = self.github_login {
- return Ok(ContributorSelector::GitHubLogin { github_login });
- }
-
- Err(anyhow::anyhow!(
- "must be one of `github_user_id` or `github_login`."
- ))?
- }
-}
-
-#[derive(Debug, Serialize)]
-struct CheckIsContributorResponse {
- signed_at: Option<String>,
-}
-
-async fn check_is_contributor(
- Extension(app): Extension<Arc<AppState>>,
- Query(params): Query<CheckIsContributorParams>,
-) -> Result<Json<CheckIsContributorResponse>> {
- let params = params.into_contributor_selector()?;
-
- if CopilotSweAgentBot::is_copilot_bot(¶ms) {
- return Ok(Json(CheckIsContributorResponse {
- signed_at: Some(
- CopilotSweAgentBot::created_at()
- .and_utc()
- .to_rfc3339_opts(SecondsFormat::Millis, true),
- ),
- }));
- }
-
- if Dependabot::is_dependabot(¶ms) {
- return Ok(Json(CheckIsContributorResponse {
- signed_at: Some(
- Dependabot::created_at()
- .and_utc()
- .to_rfc3339_opts(SecondsFormat::Millis, true),
- ),
- }));
- }
-
- if RenovateBot::is_renovate_bot(¶ms) {
- return Ok(Json(CheckIsContributorResponse {
- signed_at: Some(
- RenovateBot::created_at()
- .and_utc()
- .to_rfc3339_opts(SecondsFormat::Millis, true),
- ),
- }));
- }
-
- if ZedZippyBot::is_zed_zippy_bot(¶ms) {
- return Ok(Json(CheckIsContributorResponse {
- signed_at: Some(
- ZedZippyBot::created_at()
- .and_utc()
- .to_rfc3339_opts(SecondsFormat::Millis, true),
- ),
- }));
- }
-
- Ok(Json(CheckIsContributorResponse {
- signed_at: app
- .db
- .get_contributor_sign_timestamp(¶ms)
- .await?
- .map(|ts| ts.and_utc().to_rfc3339_opts(SecondsFormat::Millis, true)),
- }))
-}
-
-/// The Copilot bot GitHub user (`copilot-swe-agent[bot]`).
-///
-/// https://api.github.com/users/copilot-swe-agent[bot]
-struct CopilotSweAgentBot;
-
-impl CopilotSweAgentBot {
- const LOGIN: &'static str = "copilot-swe-agent[bot]";
- const USER_ID: i32 = 198982749;
- /// The alias of the GitHub copilot user. Although https://api.github.com/users/copilot
- /// yields a 404, GitHub still refers to the copilot bot user as @Copilot in some cases.
- const NAME_ALIAS: &'static str = "Copilot";
-
- /// Returns the `created_at` timestamp for the Dependabot bot user.
- fn created_at() -> &'static NaiveDateTime {
- static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
- CREATED_AT.get_or_init(|| {
- chrono::DateTime::parse_from_rfc3339("2025-02-12T20:26:08Z")
- .expect("failed to parse 'created_at' for 'copilot-swe-agent[bot]'")
- .naive_utc()
- })
- }
-
- /// Returns whether the given contributor selector corresponds to the Copilot bot user.
- fn is_copilot_bot(contributor: &ContributorSelector) -> bool {
- match contributor {
- ContributorSelector::GitHubLogin { github_login } => {
- github_login == Self::LOGIN || github_login == Self::NAME_ALIAS
- }
- ContributorSelector::GitHubUserId { github_user_id } => {
- github_user_id == &Self::USER_ID
- }
- }
- }
-}
-
-/// The Dependabot bot GitHub user (`dependabot[bot]`).
-///
-/// https://api.github.com/users/dependabot[bot]
-struct Dependabot;
-
-impl Dependabot {
- const LOGIN: &'static str = "dependabot[bot]";
- const USER_ID: i32 = 49699333;
-
- /// Returns the `created_at` timestamp for the Dependabot bot user.
- fn created_at() -> &'static NaiveDateTime {
- static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
- CREATED_AT.get_or_init(|| {
- chrono::DateTime::parse_from_rfc3339("2019-04-16T22:34:25Z")
- .expect("failed to parse 'created_at' for 'dependabot[bot]'")
- .naive_utc()
- })
- }
-
- /// Returns whether the given contributor selector corresponds to the Dependabot bot user.
- fn is_dependabot(contributor: &ContributorSelector) -> bool {
- match contributor {
- ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
- ContributorSelector::GitHubUserId { github_user_id } => {
- github_user_id == &Self::USER_ID
- }
- }
- }
-}
-
-/// The Renovate bot GitHub user (`renovate[bot]`).
-///
-/// https://api.github.com/users/renovate[bot]
-struct RenovateBot;
-
-impl RenovateBot {
- const LOGIN: &'static str = "renovate[bot]";
- const USER_ID: i32 = 29139614;
-
- /// Returns the `created_at` timestamp for the Renovate bot user.
- fn created_at() -> &'static NaiveDateTime {
- static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
- CREATED_AT.get_or_init(|| {
- chrono::DateTime::parse_from_rfc3339("2017-06-02T07:04:12Z")
- .expect("failed to parse 'created_at' for 'renovate[bot]'")
- .naive_utc()
- })
- }
-
- /// Returns whether the given contributor selector corresponds to the Renovate bot user.
- fn is_renovate_bot(contributor: &ContributorSelector) -> bool {
- match contributor {
- ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
- ContributorSelector::GitHubUserId { github_user_id } => {
- github_user_id == &Self::USER_ID
- }
- }
- }
-}
-
-/// The Zed Zippy bot GitHub user (`zed-zippy[bot]`).
-///
-/// https://api.github.com/users/zed-zippy[bot]
-struct ZedZippyBot;
-
-impl ZedZippyBot {
- const LOGIN: &'static str = "zed-zippy[bot]";
- const USER_ID: i32 = 234243425;
-
- /// Returns the `created_at` timestamp for the Zed Zippy bot user.
- fn created_at() -> &'static NaiveDateTime {
- static CREATED_AT: OnceLock<NaiveDateTime> = OnceLock::new();
- CREATED_AT.get_or_init(|| {
- chrono::DateTime::parse_from_rfc3339("2025-09-24T17:00:11Z")
- .expect("failed to parse 'created_at' for 'zed-zippy[bot]'")
- .naive_utc()
- })
- }
-
- /// Returns whether the given contributor selector corresponds to the Zed Zippy bot user.
- fn is_zed_zippy_bot(contributor: &ContributorSelector) -> bool {
- match contributor {
- ContributorSelector::GitHubLogin { github_login } => github_login == Self::LOGIN,
- ContributorSelector::GitHubUserId { github_user_id } => {
- github_user_id == &Self::USER_ID
- }
- }
- }
-}
-
#[derive(Debug, Deserialize)]
struct AddContributorBody {
github_user_id: i32,
@@ -1,11 +1,5 @@
use super::*;
-#[derive(Debug)]
-pub enum ContributorSelector {
- GitHubUserId { github_user_id: i32 },
- GitHubLogin { github_login: String },
-}
-
impl Database {
/// Retrieves the GitHub logins of all users who have signed the CLA.
pub async fn get_contributors(&self) -> Result<Vec<String>> {
@@ -27,38 +21,6 @@ impl Database {
.await
}
- /// Records that a given user has signed the CLA.
- pub async fn get_contributor_sign_timestamp(
- &self,
- selector: &ContributorSelector,
- ) -> Result<Option<DateTime>> {
- self.transaction(|tx| async move {
- let condition = match selector {
- ContributorSelector::GitHubUserId { github_user_id } => {
- user::Column::GithubUserId.eq(*github_user_id)
- }
- ContributorSelector::GitHubLogin { github_login } => {
- user::Column::GithubLogin.eq(github_login)
- }
- };
-
- if let Some(user) = user::Entity::find().filter(condition).one(&*tx).await? {
- if user.admin {
- return Ok(Some(user.created_at));
- }
-
- if let Some(contributor) =
- contributor::Entity::find_by_id(user.id).one(&*tx).await?
- {
- return Ok(Some(contributor.signed_at));
- }
- }
-
- Ok(None)
- })
- .await
- }
-
/// Records that a given user has signed the CLA.
pub async fn add_contributor(
&self,