Skip to content

Commit 23fbed6

Browse files
authored
Merge pull request #10 from thuan2172001/main
Feat: add CI into project
2 parents dab6323 + 838b6ef commit 23fbed6

File tree

9 files changed

+159
-19
lines changed

9 files changed

+159
-19
lines changed

.github/dependabot.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
version: 2
3+
updates:
4+
- package-ecosystem: "cargo"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
rebase-strategy: "disabled"

.github/workflows/ci.yaml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: Continuous Integration
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
11+
jobs:
12+
cargo-check:
13+
name: Cargo check
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions-rs/toolchain@v1
18+
with:
19+
profile: minimal
20+
toolchain: stable
21+
override: true
22+
- uses: actions-rs/cargo@v1
23+
with:
24+
command: check
25+
26+
fmt-check:
27+
name: Rust fmt
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
- uses: actions-rs/toolchain@v1
32+
with:
33+
profile: minimal
34+
toolchain: stable
35+
override: true
36+
- run: rustup component add rustfmt
37+
- uses: actions-rs/cargo@v1
38+
with:
39+
command: fmt
40+
args: --all -- --check
41+
42+
test-and-coverage:
43+
name: Test and Coverage
44+
runs-on: ubuntu-latest
45+
steps:
46+
- name: Checkout code
47+
uses: actions/checkout@v4
48+
49+
- name: Install dependencies
50+
run: |
51+
rustup self update
52+
rustup update
53+
cargo install cargo-tarpaulin
54+
55+
- name: Run tests with coverage
56+
run: |
57+
cargo tarpaulin --all-features --verbose
58+
59+
release-github-artifact:
60+
name: Release Packaging
61+
env:
62+
PROJECT_NAME_UNDERSCORE: rust-api-server
63+
runs-on: ubuntu-latest
64+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
65+
needs: [cargo-check, fmt-check, test-and-coverage]
66+
steps:
67+
- name: Check out from Git
68+
uses: actions/checkout@v4
69+
- name: Grant permission to run command
70+
run: echo 'ACTIONS_ALLOW_UNSECURE_COMMANDS=true' >> $GITHUB_ENV
71+
- name: Check if Git tag exists
72+
run: echo "::set-env name=HEAD_TAG::$(git tag --points-at HEAD)"
73+
- name: Skip if Git tag does not exist
74+
if: steps.check-tag.outputs.HEAD_TAG == ''
75+
run: exit 0 # Exit with success, effectively skipping subsequent steps
76+
77+
- uses: actions/checkout@v4
78+
- uses: actions-rs/toolchain@v1
79+
with:
80+
profile: minimal
81+
toolchain: stable
82+
override: true
83+
- name: Release Build
84+
run: cargo build --release
85+
- name: "Upload Artifact"
86+
uses: actions/upload-artifact@v2
87+
with:
88+
name: ${{ env.PROJECT_NAME_UNDERSCORE }}
89+
path: target/release/${{ env.PROJECT_NAME_UNDERSCORE }}
90+
91+
release-docker-image:
92+
runs-on: ubuntu-latest
93+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
94+
needs: [cargo-check, fmt-check, test-and-coverage]
95+
steps:
96+
- name: Check out from Git
97+
uses: actions/checkout@v4
98+
- name: Grant permission to run command
99+
run: echo 'ACTIONS_ALLOW_UNSECURE_COMMANDS=true' >> $GITHUB_ENV
100+
- name: Check if Git tag exists
101+
run: echo "::set-env name=HEAD_TAG::$(git tag --points-at HEAD)"
102+
- name: Skip if Git tag does not exist
103+
if: steps.check-tag.outputs.HEAD_TAG == ''
104+
run: exit 0 # Exit with success, effectively skipping subsequent steps
105+
106+
- name: Checkout
107+
uses: actions/checkout@v4
108+
- name: Login to Docker Hub
109+
uses: docker/login-action@v3
110+
with:
111+
username: ${{ secrets.DOCKER_USERNAME }}
112+
password: ${{ secrets.DOCKERHUB_TOKEN }}
113+
- name: Set up Docker Buildx
114+
uses: docker/setup-buildx-action@v3
115+
- name: Build and push
116+
uses: docker/build-push-action@v5
117+
with:
118+
context: .
119+
target: prod
120+
load: true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
target/
1+
target/
2+
results.xml

README.md

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ Hierarchical child config via env, separated by using `__`. Specify list values
7070

7171
Make sure to set these environment variables according to your needs before running the server.
7272

73+
## GitHub Flow CI Configuration
74+
75+
1. **Set Docker Hub Secrets:**
76+
- Go to repository Settings > Secrets.
77+
- Add `DOCKER_USERNAME` and `DOCKERHUB_TOKEN`.
78+
79+
2. **Enable Dependabot Alerts:**
80+
- In repository Insights, enable "Dependabot alerts" and "Security & Analysis."
81+
7382
## Checklist
7483

7584
### Basic Functionalities
@@ -94,11 +103,11 @@ Demonstrate proficiency in advanced development practices including:
94103
2. [x] Load Configuration from a File.
95104
3. [x] Multiple Implementations.
96105
4. [x] Advanced Tracing.
97-
5. [ ] CI/CD.
106+
5. [x] CI/CD.
98107
1. [ ] Migrate DB tool/image.
99-
2. [ ] Publish binary artifacts in [Github](https://github.com/).
100-
3. [ ] Push Docker images.
101-
4. [ ]
108+
2. [x] Publish binary artifacts in [Github](https://github.com/).
109+
3. [x] Push Docker images.
110+
4. [x]
102111
Deploy [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuring-dependabot-version-updates)
103112
6. [x] Docker Image Optimization.
104113
7. [x] Load test using [K6](https://k6.io/).

cli/src/main.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
/// // Start the server with default configuration
1616
/// main();
1717
/// ```
18+
19+
#[cfg_attr(debug_assertions, allow(dead_code, unused_imports))]
1820
use openssl;
1921

20-
#[macro_use]
22+
#[cfg_attr(debug_assertions, allow(dead_code, unused_imports))]
2123
use diesel;
2224

2325
mod options;
@@ -40,7 +42,7 @@ use std::str::FromStr;
4042
use std::sync::Arc;
4143

4244
use library::adapter::repositories::postgres::question_db::QuestionDBRepository;
43-
use tracing::{error, info};
45+
use tracing::info;
4446

4547
/// Simple REST server.
4648
#[derive(Parser, Debug)]
@@ -49,7 +51,7 @@ struct Args {
4951
#[command(subcommand)]
5052
command: Option<Commands>,
5153
/// Config file
52-
#[arg(short, long, default_value = "config/default.toml")]
54+
#[arg(short, long, default_value = "config/00-default.toml")]
5355
config_path: Vec<String>,
5456
/// Print version
5557
#[clap(short, long)]
@@ -66,7 +68,7 @@ enum Commands {
6668
#[tokio::main]
6769
async fn main() {
6870
let args = Args::parse();
69-
if args.version == true {
71+
if args.version {
7072
println!(env!("APP_VERSION"));
7173
return;
7274
}

library/src/adapter/repositories/postgres/models/question.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use serde::Serialize;
44
use std::time::SystemTime;
55

66
#[derive(Debug, Queryable, Serialize, Selectable, Insertable, AsChangeset, Identifiable)]
7-
#[table_name = "super::super::schema::questions"]
7+
#[diesel(table_name = super::super::schema::questions)]
88
#[cfg_attr(feature = "postgres", derive(diesel::pg::Pg))]
99
pub struct QuestionModel {
1010
pub id: i32,

library/src/core/ports/question.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ mod tests {
8787
assert_eq!(result.unwrap(), updated_question);
8888

8989
let result = question_port.delete(&question_id).await;
90-
assert_eq!(result.is_ok(), true);
90+
assert!(result.is_ok());
9191
}
9292

9393
#[tokio::test]
@@ -103,10 +103,10 @@ mod tests {
103103
let docker = Cli::default();
104104
let postgres_instance = docker.run(Postgres::default());
105105

106-
let database_url = String::from(format!(
106+
let database_url = format!(
107107
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
108108
postgres_instance.get_host_port_ipv4(5432)
109-
));
109+
);
110110
let database_config = DatabaseConfig {
111111
url: database_url.clone(),
112112
max_size: 10,

library/tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
mod questions_router_test;
1+
mod questions_router_test;

library/tests/questions_router_test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ mod tests {
33
postgres::{Pool, Runtime},
44
Manager,
55
};
6-
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
6+
use diesel_migrations::MigrationHarness;
77
use library::{
88
adapter::repositories::{
99
in_memory::question::QuestionInMemoryRepository,
@@ -72,7 +72,7 @@ mod tests {
7272

7373
// Deserialize the response body into a Value
7474
let get_question: QuestionEntity =
75-
serde_json::from_slice(&get_resp.body()).expect("Failed to deserialize response body");
75+
serde_json::from_slice(get_resp.body()).expect("Failed to deserialize response body");
7676

7777
assert_eq!(
7878
get_question, question,
@@ -118,7 +118,7 @@ mod tests {
118118
);
119119

120120
// Deserialize the response body into a Value
121-
let get_updated_question: QuestionEntity = serde_json::from_slice(&get_updated_resp.body())
121+
let get_updated_question: QuestionEntity = serde_json::from_slice(get_updated_resp.body())
122122
.expect("Failed to deserialize response body");
123123

124124
assert_eq!(
@@ -173,10 +173,10 @@ mod tests {
173173
let docker = Cli::default();
174174
let postgres_instance = docker.run(Postgres::default());
175175

176-
let database_url = String::from(format!(
176+
let database_url = format!(
177177
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
178178
postgres_instance.get_host_port_ipv4(5432)
179-
));
179+
);
180180
let database_config = DatabaseConfig {
181181
url: database_url.clone(),
182182
max_size: 10,

0 commit comments

Comments
 (0)