Skip to content

Commit 202b0f3

Browse files
committed
CI for the new server
1 parent a7330e4 commit 202b0f3

15 files changed

Lines changed: 156 additions & 66 deletions

File tree

.gitlab-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
include:
22
- local: .gitlab/ci/build_rs_core.yml
33
- local: .gitlab/ci/build_js_sdks.yml
4+
- local: .gitlab/ci/build_server.yml
45

56
stages:
67
- setup

.gitlab/ci/build_server.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.server-workflow:
2+
image: gitlab.futo.org:5050/devops/manifest-repo/library/docker:latest
3+
rules:
4+
- if: $CI_COMMIT_TAG =~ /^server-/
5+
when: always
6+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
7+
changes:
8+
- services/server/*
9+
- .gitlab/ci/build_server.yml
10+
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
11+
when: never
12+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
13+
changes:
14+
- services/server/*
15+
- .gitlab/ci/build_server.yml
16+
variables:
17+
RUNNER_SCRIPT_TIMEOUT: 179m
18+
DOCKER_FULL_IMAGE_NAME: '${CI_REGISTRY}/${CI_PROJECT_PATH}'
19+
RUST_IMAGE: '${CI_REGISTRY}/${CI_PROJECT_PATH}:base'
20+
before_script:
21+
- cd services/server
22+
23+
.server-rust-base:
24+
extends: .server-workflow
25+
image: ${RUST_IMAGE}
26+
stage: check
27+
28+
server-format-check:
29+
extends: .server-rust-base
30+
script:
31+
- cargo fmt --check
32+
33+
server-clippy:
34+
extends: .server-rust-base
35+
script:
36+
- cargo clippy -- -D warnings
37+
38+
server-build:
39+
extends: .server-rust-base
40+
stage: build
41+
script:
42+
- cargo build --release
43+
artifacts:
44+
paths:
45+
- target/release/server
46+
expire_in: 1 week

services/server/src/db/client.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use sea_orm::{ConnectOptions, Database, DatabaseConnection};
33
use std::time::Duration;
44

55
pub async fn build_db_client() -> Result<DatabaseConnection, sea_orm::DbErr> {
6-
let database_url = std::env::var("DATABASE_URL")
7-
.unwrap_or_else(|_| "postgres://postgres:testing@localhost:5432".to_string());
6+
let database_url = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
7+
"postgres://postgres:testing@localhost:5432".to_string()
8+
});
89
let mut opt = ConnectOptions::new(database_url);
910
opt.max_connections(100)
1011
.min_connections(5)

services/server/src/grpc/reflection_ui.rs

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use axum::response::Html;
22
use prost::Message;
33
use prost_types::{FileDescriptorSet, SourceCodeInfo};
44

5-
use crate::lib::proto::FILE_DESCRIPTOR_SET;
5+
use crate::service::proto::FILE_DESCRIPTOR_SET;
66

77
/// Resolve a path in source_code_info to find the leading comment.
88
/// Proto paths are documented in descriptor.proto's SourceCodeInfo.
@@ -19,7 +19,10 @@ fn find_comment(source_info: &SourceCodeInfo, path: &[i32]) -> Option<String> {
1919
})
2020
}
2121

22-
fn field_type_name(field: &prost_types::FieldDescriptorProto, package: &str) -> String {
22+
fn field_type_name(
23+
field: &prost_types::FieldDescriptorProto,
24+
package: &str,
25+
) -> String {
2326
if let Some(ref type_name) = field.type_name {
2427
// Strip leading dot and package prefix from fully-qualified names
2528
let stripped = type_name.strip_prefix('.').unwrap_or(type_name);
@@ -73,7 +76,8 @@ fn escape_html(s: &str) -> String {
7376
}
7477

7578
pub async fn reflection_ui() -> Html<String> {
76-
let fds = FileDescriptorSet::decode(FILE_DESCRIPTOR_SET).expect("failed to decode descriptor");
79+
let fds = FileDescriptorSet::decode(FILE_DESCRIPTOR_SET)
80+
.expect("failed to decode descriptor");
7781

7882
let mut html = String::from(
7983
r#"<!DOCTYPE html>
@@ -118,12 +122,18 @@ pub async fn reflection_ui() -> Html<String> {
118122
for (si, service) in file.service.iter().enumerate() {
119123
let service_name = service.name.as_deref().unwrap_or("Unknown");
120124

121-
html.push_str(&format!(r#"<div class="service"><h2>{}</h2>"#, escape_html(service_name)));
125+
html.push_str(&format!(
126+
r#"<div class="service"><h2>{}</h2>"#,
127+
escape_html(service_name)
128+
));
122129

123-
if let Some(ref si_info) = source_info {
124-
if let Some(comment) = find_comment(si_info, &[6, si as i32]) {
125-
html.push_str(&format!(r#"<p class="comment">{}</p>"#, escape_html(&comment)));
126-
}
130+
if let Some(si_info) = source_info
131+
&& let Some(comment) = find_comment(si_info, &[6, si as i32])
132+
{
133+
html.push_str(&format!(
134+
r#"<p class="comment">{}</p>"#,
135+
escape_html(&comment)
136+
));
127137
}
128138

129139
// Methods: path [6, service_index, 2, method_index]
@@ -146,24 +156,29 @@ pub async fn reflection_ui() -> Html<String> {
146156

147157
html.push_str(r#"<div class="method">"#);
148158

149-
if let Some(ref si_info) = source_info {
150-
if let Some(comment) = find_comment(si_info, &[6, si as i32, 2, mi as i32]) {
151-
html.push_str(&format!(
152-
r#"<p class="comment">{}</p>"#,
153-
escape_html(&comment)
154-
));
155-
}
159+
if let Some(si_info) = source_info
160+
&& let Some(comment) =
161+
find_comment(si_info, &[6, si as i32, 2, mi as i32])
162+
{
163+
html.push_str(&format!(
164+
r#"<p class="comment">{}</p>"#,
165+
escape_html(&comment)
166+
));
156167
}
157168

158169
let client_streaming = method.client_streaming.unwrap_or(false);
159170
let server_streaming = method.server_streaming.unwrap_or(false);
160171

161172
let mut tags = String::new();
162173
if client_streaming {
163-
tags.push_str(r#"<span class="tag">client streaming</span>"#);
174+
tags.push_str(
175+
r#"<span class="tag">client streaming</span>"#,
176+
);
164177
}
165178
if server_streaming {
166-
tags.push_str(r#"<span class="tag">server streaming</span>"#);
179+
tags.push_str(
180+
r#"<span class="tag">server streaming</span>"#,
181+
);
167182
}
168183
if !client_streaming && !server_streaming {
169184
tags.push_str(r#"<span class="tag">unary</span>"#);
@@ -195,10 +210,13 @@ pub async fn reflection_ui() -> Html<String> {
195210
escape_html(msg_name)
196211
));
197212

198-
if let Some(ref si_info) = source_info {
199-
if let Some(comment) = find_comment(si_info, &[4, mi as i32]) {
200-
html.push_str(&format!(r#"<p class="comment">{}</p>"#, escape_html(&comment)));
201-
}
213+
if let Some(si_info) = source_info
214+
&& let Some(comment) = find_comment(si_info, &[4, mi as i32])
215+
{
216+
html.push_str(&format!(
217+
r#"<p class="comment">{}</p>"#,
218+
escape_html(&comment)
219+
));
202220
}
203221

204222
if !message.field.is_empty() {
@@ -213,12 +231,15 @@ pub async fn reflection_ui() -> Html<String> {
213231
let flabel = label_str(field);
214232

215233
let field_comment = source_info
216-
.and_then(|si| find_comment(si, &[4, mi as i32, 2, fi as i32]))
234+
.and_then(|si| {
235+
find_comment(si, &[4, mi as i32, 2, fi as i32])
236+
})
217237
.or_else(|| {
218238
// Also check trailing comments
219239
source_info.and_then(|si| {
220240
si.location.iter().find_map(|loc| {
221-
if loc.path == [4, mi as i32, 2, fi as i32] {
241+
if loc.path == [4, mi as i32, 2, fi as i32]
242+
{
222243
loc.trailing_comments
223244
.as_ref()
224245
.map(|c| c.trim().to_string())
@@ -256,10 +277,13 @@ pub async fn reflection_ui() -> Html<String> {
256277
escape_html(enum_name)
257278
));
258279

259-
if let Some(ref si_info) = source_info {
260-
if let Some(comment) = find_comment(si_info, &[5, ei as i32]) {
261-
html.push_str(&format!(r#"<p class="comment">{}</p>"#, escape_html(&comment)));
262-
}
280+
if let Some(si_info) = source_info
281+
&& let Some(comment) = find_comment(si_info, &[5, ei as i32])
282+
{
283+
html.push_str(&format!(
284+
r#"<p class="comment">{}</p>"#,
285+
escape_html(&comment)
286+
));
263287
}
264288

265289
if !enum_type.value.is_empty() {
@@ -270,7 +294,9 @@ pub async fn reflection_ui() -> Html<String> {
270294
let vnum = value.number.unwrap_or(0);
271295

272296
let value_comment = source_info
273-
.and_then(|si| find_comment(si, &[5, ei as i32, 2, vi as i32]))
297+
.and_then(|si| {
298+
find_comment(si, &[5, ei as i32, 2, vi as i32])
299+
})
274300
.unwrap_or_default();
275301

276302
html.push_str(&format!(
@@ -290,4 +316,4 @@ pub async fn reflection_ui() -> Html<String> {
290316

291317
html.push_str("</body></html>");
292318
Html(html)
293-
}
319+
}

services/server/src/grpc/server.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::db::client::build_db_client;
2-
use crate::lib;
2+
use crate::service;
33
use tonic::transport::Server;
44

55
/// Builds reflection for gRPC docs. The file descriptors are created in ./build.rs.
@@ -10,7 +10,9 @@ fn build_reflection_service() -> Result<
1010
Box<dyn std::error::Error>,
1111
> {
1212
let service = tonic_reflection::server::Builder::configure()
13-
.register_encoded_file_descriptor_set(lib::proto::FILE_DESCRIPTOR_SET)
13+
.register_encoded_file_descriptor_set(
14+
service::proto::FILE_DESCRIPTOR_SET,
15+
)
1416
.build_v1()?;
1517
Ok(service)
1618
}
@@ -22,7 +24,9 @@ async fn connect_db_with_retry() -> sea_orm::DatabaseConnection {
2224
match build_db_client().await {
2325
Ok(db) => return db,
2426
Err(e) => {
25-
eprintln!("Failed to connect to database: {e}, retrying in {delay:?}");
27+
eprintln!(
28+
"Failed to connect to database: {e}, retrying in {delay:?}"
29+
);
2630
tokio::time::sleep(delay).await;
2731
delay = (delay * 2).min(std::time::Duration::from_secs(30));
2832
}
@@ -34,7 +38,8 @@ async fn connect_db_with_retry() -> sea_orm::DatabaseConnection {
3438
pub async fn serve_grpc() -> Result<(), Box<dyn std::error::Error>> {
3539
let addr = "0.0.0.0:50051".parse()?;
3640
let db = connect_db_with_retry().await;
37-
let events_service = lib::events::events_service::build_events_service(db);
41+
let events_service =
42+
service::events::events_service::build_events_service(db);
3843
let reflection_service = build_reflection_service()?;
3944

4045
println!("GRPC server is listening on {addr}");

services/server/src/lib/proto.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.

services/server/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod db;
22
mod grpc;
3-
mod lib;
43
mod routes;
4+
mod service;
55
mod util;
66

77
use crate::grpc::server;

services/server/src/lib/content/content_repository.rs renamed to services/server/src/service/content/content_repository.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
use ::entity::content_model as ContentModel;
22
use sea_orm::*;
33

4-
pub struct Query;
5-
6-
impl Query {}
7-
84
pub struct Mutation;
95

106
impl Mutation {
File renamed without changes.

services/server/src/lib/events/events_repository.rs renamed to services/server/src/service/events/events_repository.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ impl Query {
99
pub async fn list_events(
1010
db: &DbConn,
1111
mut limit: Option<u64>,
12-
) -> Result<Vec<(EventModel::Model, Option<ContentModel::Model>)>, DbErr> {
12+
) -> Result<Vec<(EventModel::Model, Option<ContentModel::Model>)>, DbErr>
13+
{
1314
if limit > Some(200) {
1415
limit = Some(200);
1516
}
@@ -22,9 +23,15 @@ impl Query {
2223
.from(EventModel::Column::ContentDigestType)
2324
.to(ContentModel::Column::DigestType)
2425
.on_condition(|event_tbl, content_tbl| {
25-
Expr::col((event_tbl, EventModel::Column::ContentDigestBytes))
26-
.equals((content_tbl, ContentModel::Column::DigestBytes))
27-
.into_condition()
26+
Expr::col((
27+
event_tbl,
28+
EventModel::Column::ContentDigestBytes,
29+
))
30+
.equals((
31+
content_tbl,
32+
ContentModel::Column::DigestBytes,
33+
))
34+
.into_condition()
2835
})
2936
.into(),
3037
)

0 commit comments

Comments
 (0)