feat: install workspace backend config template
This commit is contained in:
parent
8b1e4b721f
commit
a123db83ad
|
|
@ -2,7 +2,7 @@
|
||||||
title: 'Workspace Backend設定ファイルのスキーマを定義する'
|
title: 'Workspace Backend設定ファイルのスキーマを定義する'
|
||||||
state: 'closed'
|
state: 'closed'
|
||||||
created_at: '2026-07-01T14:41:48Z'
|
created_at: '2026-07-01T14:41:48Z'
|
||||||
updated_at: '2026-07-01T15:48:28Z'
|
updated_at: '2026-07-01T16:38:31Z'
|
||||||
assignee: null
|
assignee: null
|
||||||
queued_by: 'yoi ticket'
|
queued_by: 'yoi ticket'
|
||||||
queued_at: '2026-07-01T15:32:38Z'
|
queued_at: '2026-07-01T15:32:38Z'
|
||||||
|
|
|
||||||
|
|
@ -129,4 +129,29 @@ Validation:
|
||||||
- `nix build .#yoi --no-link`
|
- `nix build .#yoi --no-link`
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- event: implementation_report author: hare at: 2026-07-01T16:38:31Z -->
|
||||||
|
|
||||||
|
## Implementation report
|
||||||
|
|
||||||
|
Moved the Workspace Backend default config template into runtime resources and wired init-time copying.
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
- Added `resources/workspace-backend.default.toml` as the packaged template source.
|
||||||
|
- Embedded the template with `include_str!` from `workspace-server::config`.
|
||||||
|
- Added `.yoi/workspace-backend.default.toml` as the workspace-local copied template path.
|
||||||
|
- `yoi-workspace-server serve` now ensures the default template exists after workspace identity initialization and before reading `.local` config.
|
||||||
|
- Copying uses create-new semantics and does not overwrite an existing workspace-local default template.
|
||||||
|
- Removed the previously untracked `.yoi/workspace-backend.default.toml` workspace copy from the repository root.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
- `cargo fmt --check`
|
||||||
|
- `cargo test -p yoi-workspace-server`
|
||||||
|
- `cargo check -p yoi`
|
||||||
|
- TOML parse check with Deno
|
||||||
|
- `git diff --check`
|
||||||
|
- `nix build .#yoi --no-link`
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ use crate::server::{AuthConfig, ServerConfig};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
pub const WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH: &str = ".yoi/workspace-backend.local.toml";
|
pub const WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH: &str = ".yoi/workspace-backend.local.toml";
|
||||||
|
pub const WORKSPACE_BACKEND_DEFAULT_CONFIG_RELATIVE_PATH: &str =
|
||||||
|
".yoi/workspace-backend.default.toml";
|
||||||
|
pub const WORKSPACE_BACKEND_DEFAULT_CONFIG_TEMPLATE: &str =
|
||||||
|
include_str!("../../../resources/workspace-backend.default.toml");
|
||||||
const DEFAULT_LISTEN: &str = "127.0.0.1:8787";
|
const DEFAULT_LISTEN: &str = "127.0.0.1:8787";
|
||||||
const DEFAULT_FRONTEND_URL: &str = "http://127.0.0.1:5173";
|
const DEFAULT_FRONTEND_URL: &str = "http://127.0.0.1:5173";
|
||||||
const DEFAULT_MAX_RECORDS: usize = 200;
|
const DEFAULT_MAX_RECORDS: usize = 200;
|
||||||
|
|
@ -88,6 +92,33 @@ impl WorkspaceBackendConfigFile {
|
||||||
.join(WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH)
|
.join(WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_template_path_for_workspace(workspace_root: impl AsRef<Path>) -> PathBuf {
|
||||||
|
workspace_root
|
||||||
|
.as_ref()
|
||||||
|
.join(WORKSPACE_BACKEND_DEFAULT_CONFIG_RELATIVE_PATH)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ensure_default_template_for_workspace(workspace_root: impl AsRef<Path>) -> Result<()> {
|
||||||
|
let path = Self::default_template_path_for_workspace(workspace_root);
|
||||||
|
if let Some(parent) = path.parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
match fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create_new(true)
|
||||||
|
.open(&path)
|
||||||
|
{
|
||||||
|
Ok(mut file) => {
|
||||||
|
use std::io::Write;
|
||||||
|
file.write_all(WORKSPACE_BACKEND_DEFAULT_CONFIG_TEMPLATE.as_bytes())?;
|
||||||
|
file.sync_all()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(error) if error.kind() == io::ErrorKind::AlreadyExists => Ok(()),
|
||||||
|
Err(error) => Err(Error::Io(error)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_for_workspace(workspace_root: impl AsRef<Path>) -> Result<Self> {
|
pub fn load_for_workspace(workspace_root: impl AsRef<Path>) -> Result<Self> {
|
||||||
let path = Self::path_for_workspace(workspace_root);
|
let path = Self::path_for_workspace(workspace_root);
|
||||||
match fs::read_to_string(&path) {
|
match fs::read_to_string(&path) {
|
||||||
|
|
@ -335,6 +366,20 @@ root = ".local-data"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn copies_default_template_without_overwriting() {
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
WorkspaceBackendConfigFile::ensure_default_template_for_workspace(dir.path()).unwrap();
|
||||||
|
let path = WorkspaceBackendConfigFile::default_template_path_for_workspace(dir.path());
|
||||||
|
let raw = fs::read_to_string(&path).unwrap();
|
||||||
|
assert_eq!(raw, WORKSPACE_BACKEND_DEFAULT_CONFIG_TEMPLATE);
|
||||||
|
WorkspaceBackendConfigFile::parse_str(&raw, &path).unwrap();
|
||||||
|
|
||||||
|
fs::write(&path, "# custom template\n").unwrap();
|
||||||
|
WorkspaceBackendConfigFile::ensure_default_template_for_workspace(dir.path()).unwrap();
|
||||||
|
assert_eq!(fs::read_to_string(&path).unwrap(), "# custom template\n");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn token_value_field_is_not_in_schema() {
|
fn token_value_field_is_not_in_schema() {
|
||||||
let error = WorkspaceBackendConfigFile::parse_str(
|
let error = WorkspaceBackendConfigFile::parse_str(
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub mod store;
|
||||||
|
|
||||||
pub use config::{
|
pub use config::{
|
||||||
ResolvedWorkspaceBackendConfig, WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH,
|
ResolvedWorkspaceBackendConfig, WORKSPACE_BACKEND_CONFIG_RELATIVE_PATH,
|
||||||
WorkspaceBackendConfigFile,
|
WORKSPACE_BACKEND_DEFAULT_CONFIG_RELATIVE_PATH, WorkspaceBackendConfigFile,
|
||||||
};
|
};
|
||||||
pub use identity::{WORKSPACE_IDENTITY_RELATIVE_PATH, WorkspaceIdentity};
|
pub use identity::{WORKSPACE_IDENTITY_RELATIVE_PATH, WorkspaceIdentity};
|
||||||
pub use records::{
|
pub use records::{
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
async fn run_serve(options: ServeOptions) -> Result<(), Box<dyn std::error::Error>> {
|
async fn run_serve(options: ServeOptions) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let identity = WorkspaceIdentity::load_or_init(&options.workspace)?;
|
let identity = WorkspaceIdentity::load_or_init(&options.workspace)?;
|
||||||
|
WorkspaceBackendConfigFile::ensure_default_template_for_workspace(&options.workspace)?;
|
||||||
let config_file = WorkspaceBackendConfigFile::load_for_workspace(&options.workspace)?;
|
let config_file = WorkspaceBackendConfigFile::load_for_workspace(&options.workspace)?;
|
||||||
let mut resolved = config_file.resolve(&options.workspace, identity)?;
|
let mut resolved = config_file.resolve(&options.workspace, identity)?;
|
||||||
if let Some(db) = options.db {
|
if let Some(db) = options.db {
|
||||||
|
|
|
||||||
45
resources/workspace-backend.default.toml
Normal file
45
resources/workspace-backend.default.toml
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Workspace Backend local config template.
|
||||||
|
#
|
||||||
|
# Copied to `.yoi/workspace-backend.default.toml` during workspace init.
|
||||||
|
# Copy that file to `.yoi/workspace-backend.local.toml` and edit it.
|
||||||
|
# The `.local` file is intentionally git-ignored.
|
||||||
|
#
|
||||||
|
# Omit a key to use the built-in default. TOML has no `null`, so optional
|
||||||
|
# settings are represented by leaving the key commented out.
|
||||||
|
|
||||||
|
[server]
|
||||||
|
# Backend HTTP/WebSocket listen address.
|
||||||
|
listen = "127.0.0.1:8787"
|
||||||
|
|
||||||
|
# Browser-facing frontend URL used by local tooling/display.
|
||||||
|
frontend_url = "http://127.0.0.1:5173"
|
||||||
|
|
||||||
|
# Static SPA build directory override. Leave commented for dev/API-only mode.
|
||||||
|
# Relative paths are resolved from the workspace root.
|
||||||
|
# static_assets_dir = "web/workspace/dist"
|
||||||
|
|
||||||
|
[data]
|
||||||
|
# Backend data root override. Leave commented to use the user-data default:
|
||||||
|
# <data_dir>/workspace-server/<workspace_id>/
|
||||||
|
# Relative paths are resolved from the workspace root.
|
||||||
|
# root = ".yoi/workspace-backend.data"
|
||||||
|
|
||||||
|
# Explicit control-plane SQLite DB path override.
|
||||||
|
# If omitted, this defaults to `<data.root>/workspace.db`.
|
||||||
|
# workspace_database_path = ".yoi/workspace-backend.data/workspace.db"
|
||||||
|
|
||||||
|
# Explicit embedded Runtime fs-store root override.
|
||||||
|
# If omitted, this defaults to `<data.root>/embedded-runtime`.
|
||||||
|
# embedded_runtime_store_root = ".yoi/workspace-backend.data/embedded-runtime"
|
||||||
|
|
||||||
|
[limits]
|
||||||
|
max_records = 200
|
||||||
|
|
||||||
|
# Remote Runtime sources. Token values must not be written here.
|
||||||
|
# Use token_ref only after secret-ref resolution is implemented for this config.
|
||||||
|
#
|
||||||
|
# [[runtimes.remote]]
|
||||||
|
# id = "example"
|
||||||
|
# endpoint = "http://127.0.0.1:8790"
|
||||||
|
# display_name = "Example Runtime"
|
||||||
|
# token_ref = "local:example-runtime-token"
|
||||||
Loading…
Reference in New Issue
Block a user