You've already forked pages
forked from didirus/AstralRinth
feat(labrinth): database seed data fixtures for better installation and testing (#4132)
* feat(labrinth): database seed data fixtures for better installation and testing * chore(labrinth): simplify and fixup seed data fixture * docs(contributing/labrinth): enable all useful features for `sqlx-cli` install * chore(docs/labrinth): fix typo * chore(docs/labrinth): fix `cargo fmt` parameter typo * chore: replace Labrinth -> labrinth
This commit is contained in:
committed by
GitHub
parent
8af65f58d9
commit
3b8cd661bc
2
.github/workflows/turbo-ci.yml
vendored
2
.github/workflows/turbo-ci.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
- name: ⚙️ Start services
|
||||
run: docker compose up --wait
|
||||
|
||||
- name: ⚙️ Setup Labrinth environment and database
|
||||
- name: ⚙️ Setup labrinth environment and database
|
||||
working-directory: apps/labrinth
|
||||
run: |
|
||||
cp .env.local .env
|
||||
|
||||
@@ -3,59 +3,41 @@ title: Labrinth (API)
|
||||
description: Guide for contributing to Modrinth's backend
|
||||
---
|
||||
|
||||
This project is part of our [monorepo](https://github.com/modrinth/code). You can find it in the `apps/labrinth` directory.
|
||||
This project is part of our [monorepo](https://github.com/modrinth/code). You can find it in the `apps/labrinth` directory. The instructions below assume that you have switched your working directory to the `apps/labrinth` subdirectory.
|
||||
|
||||
[labrinth] is the Rust-based backend serving Modrinth's API with the help of the [Actix](https://actix.rs) framework. To get started with a labrinth instance, install docker, docker-compose (which comes with Docker), and [Rust]. The initial startup can be done simply with the command `docker-compose up`, or with `docker compose up` (Compose V2 and later). That will deploy a PostgreSQL database on port 5432 and a MeiliSearch instance on port 7700. To run the API itself, you'll need to use the `cargo run` command, this will deploy the API on port 8000.
|
||||
|
||||
To get a basic configuration, copy the `.env.local` file to `.env`. Now, you'll have to install the sqlx CLI, which can be done with cargo:
|
||||
|
||||
```bash
|
||||
cargo install --git https://github.com/launchbadge/sqlx sqlx-cli --no-default-features --features postgres,rustls
|
||||
```sh
|
||||
cargo install sqlx-cli --no-default-features --features mysql,sqlite,postgres,rustls,completions
|
||||
```
|
||||
|
||||
From there, you can create the database and perform all database migrations with one simple command:
|
||||
From there, you can create the database and set up its schema with one simple command:
|
||||
|
||||
```bash
|
||||
sqlx database setup
|
||||
```sh
|
||||
cargo sqlx database setup
|
||||
```
|
||||
|
||||
To enable labrinth to create a project, you need to add two things.
|
||||
To enable labrinth to create projects and serve useful metadata to the frontend build scripts, you'll need to seed the database with several key entities:
|
||||
|
||||
1. An entry in the `loaders` table.
|
||||
2. An entry in the `loaders_project_types` table.
|
||||
1. Categories, in the `categories` table.
|
||||
2. Loaders and their fields, in the `loaders`, `loader_fields`, `loader_field_enums`, `loader_field_enum_values`, and `loader_fields_loaders` tables.
|
||||
3. Project types and their allowed loaders and games, in the `project_types`, `loaders_project_types`, and `loaders_project_types_games` tables.
|
||||
4. Optionally, to moderate projects from the frontend, an admin user, in the `users` table.
|
||||
|
||||
A minimal setup can be done from the command line with [psql](https://www.postgresql.org/docs/current/app-psql.html):
|
||||
The most convenient way to do this seeding is with the [psql](https://www.postgresql.org/docs/current/app-psql.html) command line tool and the pre-existing seed data fixture. This fixture was generated by dumping the official staging environment database at a specific point in time, and defines an admin user with email `admin@modrinth.invalid` and password `admin`:
|
||||
|
||||
```bash
|
||||
psql --host=localhost --port=5432 -U <username, default is labrinth> -W
|
||||
```sh
|
||||
source .env
|
||||
psql "$DATABASE_URL" < fixtures/labrinth-seed-data-202508052143.sql
|
||||
```
|
||||
|
||||
The default password for the database is `labrinth`. Once you've connected, run
|
||||
|
||||
```sql
|
||||
INSERT INTO loaders VALUES (0, 'placeholder_loader');
|
||||
INSERT INTO loaders_project_types VALUES (0, 1); -- modloader id, supported type id
|
||||
INSERT INTO categories VALUES (0, 'placeholder_category', 1); -- category id, category, project type id
|
||||
```
|
||||
|
||||
This will initialize your database with a modloader called 'placeholder_loader', with id 0, and marked as supporting mods only. It will also create a category called 'placeholder_category' that is marked as supporting mods only
|
||||
If you would like 'placeholder_loader' to be marked as supporting modpacks too, run
|
||||
|
||||
```sql
|
||||
INSERT INTO loaders_project_types VALUES (0, 2); -- modloader id, supported type id
|
||||
```
|
||||
|
||||
If you would like 'placeholder_category' to be marked as supporting modpacks too, run
|
||||
|
||||
```sql
|
||||
INSERT INTO categories VALUES (0, 'placeholder_category', 2); -- modloader id, supported type id
|
||||
```
|
||||
|
||||
You can find more example SQL statements for seeding the database in the `apps/labrinth/tests/files/dummy_data.sql` file.
|
||||
You can find more example SQL statements for seeding the database in the `tests/files/dummy_data.sql` file.
|
||||
|
||||
The majority of configuration is done at runtime using [dotenvy](https://crates.io/crates/dotenvy) and the `.env` file. Each of the variables and what they do can be found in the dropdown below. Additionally, there are three command line options that can be used to specify to MeiliSearch what you want to do.
|
||||
|
||||
During development, you might notice that changes made directly to entities in the PostgreSQL database do not seem to take effect. This is often because the Redis cache still holds outdated data. To ensure your updates are reflected, clear the cache by e.g. running `redis-cli FLUSHALL`, which will force Labrinth to fetch the latest data from the database the next time it is needed.
|
||||
During development, you might notice that changes made directly to entities in the PostgreSQL database do not seem to take effect. This is often because the Redis cache still holds outdated data. To ensure your updates are reflected, clear the cache by e.g. running `redis-cli FLUSHALL`, which will force labrinth to fetch the latest data from the database the next time it is needed.
|
||||
|
||||
<details>
|
||||
<summary>.env variables & command line options</summary>
|
||||
@@ -109,14 +91,13 @@ The OAuth configuration options are fairly self-explanatory. For help setting up
|
||||
|
||||
If you're prepared to contribute by submitting a pull request, ensure you have met the following criteria:
|
||||
|
||||
- `cargo fmt` has been run.
|
||||
- `cargo clippy` has been run.
|
||||
- `cargo check` has been run.
|
||||
- `cargo fmt --all` has been run.
|
||||
- `cargo clippy --all-targets` has been run.
|
||||
- `cargo sqlx prepare` has been run.
|
||||
|
||||
> Note: If you encounter issues with `sqlx` saying 'no queries found' after running `cargo sqlx prepare`, you may need to ensure the installed version of `sqlx-cli` matches the current version of `sqlx` used [in labrinth](https://github.com/modrinth/labrinth/blob/master/Cargo.toml).
|
||||
|
||||
[Discord]: https://discord.modrinth.com
|
||||
[GitHub]: https://github.com/modrinth
|
||||
[labrinth]: https://github.com/modrinth/labrinth
|
||||
[labrinth]: https://github.com/modrinth/code/tree/main/apps/labrinth
|
||||
[Rust]: https://www.rust-lang.org/tools/install
|
||||
|
||||
1108
apps/labrinth/fixtures/labrinth-seed-data-202508052143.sql
Normal file
1108
apps/labrinth/fixtures/labrinth-seed-data-202508052143.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
"lint": "cargo fmt --check && cargo clippy --all-targets",
|
||||
"fix": "cargo clippy --all-targets --fix --allow-dirty && cargo fmt",
|
||||
"dev": "cargo run",
|
||||
"//": "Labrinth integration tests require a lot of disk space, so in the standard GitHub Actions",
|
||||
"//": "labrinth integration tests require a lot of disk space, so in the standard GitHub Actions",
|
||||
"//": "runners we must remove useless development tools from the base image, which frees up ~20 GiB.",
|
||||
"//": "The command commented out below can be used in CI to debug what is taking up space:",
|
||||
"//": "sudo du -xh --max-depth=4 / | sort -rh | curl -X POST --data-urlencode content@/dev/fd/0 https://api.mclo.gs/1/log",
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn app_setup(
|
||||
enable_background_tasks: bool,
|
||||
) -> LabrinthConfig {
|
||||
info!(
|
||||
"Starting Labrinth on {}",
|
||||
"Starting labrinth on {}",
|
||||
dotenvy::var("BIND_ADDR").unwrap()
|
||||
);
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ async fn main() -> std::io::Result<()> {
|
||||
|
||||
if args.run_background_task.is_none() {
|
||||
info!(
|
||||
"Starting Labrinth on {}",
|
||||
"Starting labrinth on {}",
|
||||
dotenvy::var("BIND_ADDR").unwrap()
|
||||
);
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ pub fn jemalloc_memory_stats(
|
||||
) -> Result<(), prometheus::Error> {
|
||||
let allocated_mem = IntGauge::new(
|
||||
"labrinth_memory_allocated",
|
||||
"Labrinth allocated memory",
|
||||
"labrinth allocated memory",
|
||||
)?;
|
||||
let resident_mem =
|
||||
IntGauge::new("labrinth_resident_memory", "Labrinth resident memory")?;
|
||||
IntGauge::new("labrinth_resident_memory", "labrinth resident memory")?;
|
||||
|
||||
registry.register(Box::new(allocated_mem.clone()))?;
|
||||
registry.register(Box::new(resident_mem.clone()))?;
|
||||
|
||||
@@ -292,7 +292,7 @@ pub async fn add_dummy_data(api: &ApiV3, db: TemporaryDatabase) -> DummyData {
|
||||
let pool = &db.pool.clone();
|
||||
|
||||
pool.execute(
|
||||
include_str!("../files/dummy_data.sql")
|
||||
include_str!("../fixtures/dummy_data.sql")
|
||||
.replace("$1", &Scopes::all().bits().to_string())
|
||||
.as_str(),
|
||||
)
|
||||
|
||||
@@ -763,7 +763,7 @@ pub async fn try_update_playtime(path: &str) -> crate::Result<()> {
|
||||
let updated_recent_playtime = profile.recent_time_played;
|
||||
|
||||
let res = if updated_recent_playtime > 0 {
|
||||
// Create update struct to send to Labrinth
|
||||
// Create update struct to send to labrinth
|
||||
let modrinth_pack_version_id =
|
||||
profile.linked_data.as_ref().map(|l| l.version_id.clone());
|
||||
let playtime_update_json = json!({
|
||||
|
||||
@@ -198,7 +198,7 @@ pub async fn finish_login_flow(
|
||||
semaphore: &FetchSemaphore,
|
||||
exec: impl sqlx::Executor<'_, Database = sqlx::Sqlite>,
|
||||
) -> crate::Result<ModrinthCredentials> {
|
||||
// The authorization code actually is the access token, since Labrinth doesn't
|
||||
// The authorization code actually is the access token, since labrinth doesn't
|
||||
// issue separate authorization codes. Therefore, this is equivalent to an
|
||||
// implicit OAuth grant flow, and no additional exchanging or finalization is
|
||||
// needed. TODO not do this for the reasons outlined at
|
||||
|
||||
Reference in New Issue
Block a user