Compare commits
2 Commits
d7375fa7ae
...
1163d2a3f3
Author | SHA1 | Date | |
---|---|---|---|
1163d2a3f3 | |||
fcdb10a7ff |
58
scripts/set-webook.py
Executable file
58
scripts/set-webook.py
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
import os
|
||||
import requests
|
||||
import secrets
|
||||
import sys
|
||||
|
||||
|
||||
def die(s):
|
||||
print(s, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
gitlab_token = os.getenv('GITLAB_TOKEN')
|
||||
if gitlab_token is None:
|
||||
die("GITLAB_TOKEN must be set in the environment")
|
||||
|
||||
if len(sys.argv) < 4:
|
||||
die("Usage: {} GITLAB_INSTANCE HOOK_URL_BASE NAMESPACE/REPO\n\nExample: {} gitlab.example.com https://bot.example.com/bebot stuff/myrepo")
|
||||
|
||||
gitlab_instance = sys.argv[1]
|
||||
hook_url = f"{sys.argv[2]}/hooks/gitlab"
|
||||
repo_name = sys.argv[3]
|
||||
|
||||
gl_base = 'https://{}/api/v4/projects/{}/hooks'.format(
|
||||
gitlab_instance,
|
||||
re.sub('/', '%2F', repo_name)
|
||||
)
|
||||
headers = {
|
||||
'authorization': 'Bearer {}'.format(gitlab_token),
|
||||
}
|
||||
payload = {
|
||||
"merge_requests_events": True,
|
||||
"pipeline_events": True,
|
||||
"push_events": True,
|
||||
"tag_push_events": True,
|
||||
}
|
||||
|
||||
resp = requests.get(gl_base, headers=headers)
|
||||
if resp.status_code != 200:
|
||||
resp.raise_for_status()
|
||||
existing = resp.json()
|
||||
|
||||
for hook in existing:
|
||||
if hook['url'] == hook_url:
|
||||
upd_url = '{}/{}'.format(gl_base, hook['id'])
|
||||
resp = requests.put(upd_url, headers=headers, json=payload)
|
||||
print("Updated existing hook")
|
||||
sys.exit(0)
|
||||
|
||||
token = secrets.token_urlsafe(32)
|
||||
payload["url"] = hook_url
|
||||
payload["token"] = token
|
||||
resp = requests.post(gl_base, headers=headers, json=payload)
|
||||
resp.raise_for_status()
|
||||
print(' "{}/{}":'.format(gitlab_instance, repo_name))
|
||||
print(' token: "{}"'.format(token))
|
115
src/event.rs
115
src/event.rs
@ -2,8 +2,7 @@ pub trait GitlabEventExt {
|
||||
fn project(&self) -> &Project;
|
||||
fn r#ref(&self) -> &str;
|
||||
fn user(&self) -> &str;
|
||||
fn url(&self) -> String;
|
||||
fn title(&self) -> String;
|
||||
fn titles(&self) -> Vec<String>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@ -70,6 +69,7 @@ impl MergeRequestAction {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct MergeRequestObjectAttributes {
|
||||
pub iid: u64,
|
||||
pub target_branch: String,
|
||||
pub source_branch: String,
|
||||
pub title: String,
|
||||
@ -158,7 +158,7 @@ pub enum GitlabEvent {
|
||||
#[serde(rename = "pipeline")]
|
||||
Pipeline {
|
||||
object_attributes: PipelineObjectAttributes,
|
||||
merge_request: PipelineMergeRequest,
|
||||
merge_request: Option<PipelineMergeRequest>,
|
||||
user: User,
|
||||
project: Project,
|
||||
},
|
||||
@ -192,56 +192,101 @@ impl GitlabEventExt for GitlabEvent {
|
||||
}
|
||||
}
|
||||
|
||||
fn url(&self) -> String {
|
||||
let url = match self {
|
||||
GitlabEvent::Push { after, project, .. } => format!("{}/-/commits/{}", project.web_url, after),
|
||||
GitlabEvent::TagPush {
|
||||
r#ref,
|
||||
checkout_sha,
|
||||
project,
|
||||
..
|
||||
} => {
|
||||
let refname = r#ref.split('/').into_iter().last().unwrap_or(checkout_sha);
|
||||
format!("{}/-/tags/{}", project.web_url, refname)
|
||||
}
|
||||
GitlabEvent::MergeRequest { object_attributes, .. } => object_attributes.url.clone(),
|
||||
GitlabEvent::Pipeline { object_attributes, .. } => object_attributes.url.clone(),
|
||||
};
|
||||
|
||||
url.replace("http://", "https://").to_string()
|
||||
}
|
||||
|
||||
fn title(&self) -> String {
|
||||
fn titles(&self) -> Vec<String> {
|
||||
fn find_commit<'a>(commits: &'a Vec<Commit>, sha: &str) -> Option<&'a Commit> {
|
||||
commits.iter().find(|commit| commit.id == sha)
|
||||
}
|
||||
|
||||
match self {
|
||||
GitlabEvent::Push { after, commits, .. } => find_commit(commits, &after)
|
||||
.map(|commit| commit.title.clone())
|
||||
.unwrap_or_else(|| "New commit(s) pushed".to_string()),
|
||||
GitlabEvent::Push {
|
||||
after,
|
||||
project,
|
||||
commits,
|
||||
..
|
||||
} => {
|
||||
const MAX_COMMITS: usize = 15; // TODO: make configurable
|
||||
commits.iter().fold(Vec::new(), |mut titles, commit| {
|
||||
if titles.len() < MAX_COMMITS {
|
||||
titles.push(format!("[**pushed** {}]({})", commit.title, commit.url));
|
||||
|
||||
if titles.len() == MAX_COMMITS {
|
||||
titles.push(format!(
|
||||
"[**pushed** {} more commits]({}/-/compare/{}...{})",
|
||||
commits.len() - MAX_COMMITS,
|
||||
project.web_url,
|
||||
commit.id,
|
||||
after
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
titles
|
||||
})
|
||||
}
|
||||
GitlabEvent::TagPush {
|
||||
checkout_sha, commits, ..
|
||||
} => find_commit(commits, &checkout_sha)
|
||||
.iter()
|
||||
.fold("New tag pushed".to_string(), |accum, commit| {
|
||||
format!("{} ({})", accum, commit.title)
|
||||
}),
|
||||
r#ref,
|
||||
checkout_sha,
|
||||
project,
|
||||
commits,
|
||||
..
|
||||
} => {
|
||||
let title = format!(
|
||||
"**tagged** {}",
|
||||
find_commit(commits, &checkout_sha)
|
||||
.map(|commit| &commit.title)
|
||||
.unwrap_or(checkout_sha)
|
||||
);
|
||||
let url = format!("{}/-/tags/{}", project.web_url, parse_ref(r#ref));
|
||||
vec![markdown_link(&title, &url)]
|
||||
}
|
||||
GitlabEvent::MergeRequest { object_attributes, .. } => {
|
||||
format!("MR {}: {}", object_attributes.action.as_str(), object_attributes.title)
|
||||
let title = format!(
|
||||
"MR !{} **{}**: {}",
|
||||
object_attributes.iid,
|
||||
object_attributes.action.as_str(),
|
||||
object_attributes.title
|
||||
);
|
||||
vec![markdown_link(&title, &object_attributes.url)]
|
||||
}
|
||||
GitlabEvent::Pipeline {
|
||||
object_attributes,
|
||||
merge_request,
|
||||
..
|
||||
} => {
|
||||
let title = object_attributes.name.as_ref().unwrap_or(&merge_request.title);
|
||||
format!("Pipeline {}: {}", object_attributes.status.as_str(), title)
|
||||
let title = object_attributes
|
||||
.name
|
||||
.as_ref()
|
||||
.map(|n| n.clone())
|
||||
.or(merge_request.as_ref().map(|mr| mr.title.clone()))
|
||||
.iter()
|
||||
.fold(
|
||||
format!("Pipeline **{}**", object_attributes.status.as_str()),
|
||||
|accum, title| format!("{}: {}", accum, title),
|
||||
);
|
||||
vec![markdown_link(&title, &object_attributes.url)]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn markdown_link(title: &String, url: &String) -> String {
|
||||
format!("[{}]({})", title, url)
|
||||
}
|
||||
|
||||
pub fn parse_ref(r#ref: &str) -> String {
|
||||
if r#ref.starts_with("refs/") {
|
||||
let parts = r#ref.split('/').collect::<Vec<_>>();
|
||||
if parts.len() > 2 {
|
||||
parts.into_iter().skip(2).collect::<Vec<_>>().join("/").to_string()
|
||||
} else {
|
||||
r#ref.to_string()
|
||||
}
|
||||
} else {
|
||||
r#ref.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
45
src/main.rs
45
src/main.rs
@ -105,28 +105,22 @@ async fn ensure_matrix_room_joined(matrix_client: &Client, room_id: &OwnedRoomOr
|
||||
room.ok_or_else(|| anyhow!("Unable to join room {}", room_id))
|
||||
}
|
||||
|
||||
fn build_gitlab_message(event: &GitlabEvent) -> String {
|
||||
fn build_gitlab_messages(event: &GitlabEvent) -> Vec<String> {
|
||||
let project = event.project();
|
||||
let r = event.r#ref();
|
||||
let refname = if r.starts_with("refs/") {
|
||||
let parts = r.split('/').collect::<Vec<_>>();
|
||||
if parts.len() > 2 {
|
||||
parts.into_iter().skip(2).collect::<Vec<_>>().join("/").to_string()
|
||||
} else {
|
||||
drop(parts);
|
||||
r.to_string()
|
||||
}
|
||||
} else {
|
||||
r.to_string()
|
||||
};
|
||||
format!(
|
||||
"*{}* {} **{}** [{}]({})",
|
||||
project.path_with_namespace,
|
||||
refname,
|
||||
event.user(),
|
||||
event.title(),
|
||||
event.url()
|
||||
)
|
||||
let refname = event::parse_ref(event.r#ref());
|
||||
event
|
||||
.titles()
|
||||
.iter()
|
||||
.map(|title| {
|
||||
format!(
|
||||
"\\[{}\\] `{}` *{}* {}",
|
||||
project.path_with_namespace,
|
||||
refname,
|
||||
event.user(),
|
||||
title,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn handle_gitlab_event(
|
||||
@ -145,10 +139,11 @@ async fn handle_gitlab_event(
|
||||
}
|
||||
|
||||
let room = ensure_matrix_room_joined(matrix_client, room_id).await?;
|
||||
let msg = build_gitlab_message(&event);
|
||||
debug!("Sending message to {}: {}", room_id, msg);
|
||||
let msg_content = RoomMessageEventContent::text_markdown(&msg);
|
||||
room.send(msg_content, None).await?;
|
||||
for msg in build_gitlab_messages(&event) {
|
||||
debug!("Sending message to {}: {}", room_id, msg);
|
||||
let msg_content = RoomMessageEventContent::text_markdown(&msg);
|
||||
room.send(msg_content, None).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user