# cli tool We're going to make a tool which objective is to sync .env variables between different machines and team members; Предполагается, что cli общается с сервером, имплементация которого остаётся за рамками этого спринта. При этом, нужно понимать, что сервер существует и для упрощения дальнейшей разработки задать вопросы и подготовить документацию для дальнейшего кодирования сервера. Сам сервер мы не проектируем, но описываем интерфейс для работы с ним, чтобы сервер можно было замокать и тестировать CLI приложение. Язык разработки golang. ## Stories ### Read projects list cmd: `aevs project -l` (or `--list`) shows project's list from the server ```md uuid | name ``` ### Update project (project's name) cmd: `aevs project save -n "project_name"` (or `--name`) optional: - `-c, --config` to identify config path to use parseConfig to get project variable (project_id); - `-i --id` to identify project's id w/o reading config; ### Delete project cmd: `aevs project remove --id {uuid.UUID}` (or `-r`) removes project's envs from the server; asks user to type project's name to proof that user really wants to delete project from the server; ### Read remote project's environments cmd: by uuid: `aevs project read --id {uuid.UUID}` (or `--read-id`) cmd: by name: `aevs project read --name {name}` (or `--read-name`) shows project's environment's list w/ version indentation: f.e.: ```md version_creation_timestamp | version_name | creator | branch_name | active/inactive - production | relative_path - development | relative_path - local | relative_path ``` ### Sync project's environments by config cmd: `aevs sync` - `-c, --config [FILE_PATH]` identifies path to config to use with `parseConfig`, if not provided tries to read `DEFAULT_CONFIG` path; fails w/ an error "no config found" if no config found; - THEN uses `parseLocals` to read local env files - THEN makes server request to retrieve version's environments (listed at the config only); - if version is inactive, server responds w/ latest version data; - THEN makes diffs map - THEN recursively asks what environments to save at the local files (new environments should be added to a local map w/o questions) here's two options: - result files creates new version (updates local env files and saves new version at the server); ### Merge versions cmd: `aevs merge` mandatory flags: - `-v, --version` - the list of space separate versions (timestamp) to be merged into a single one optional flag) - `-n, --name` - new version's name Gets version's environments and asks user to select which version is correct; If name is not provided - set timestamp as a version's name; All merged versions becomes `inactive`; ## Functions ### parseConfig Parse provided directory and search for a config file (file path should be provided or `DEFAULT_CONFIG` path would be used). Reads this file to retrieve: - project_id (uuid.UUID); - version_id (timestamp); - api_key (string); - active environment's names and paths to it's files ```yaml project: "11111111-1111-1111-1111-0123456789ab" api_key: "this-is-my-key" version: "12341234" environments: production: path: "production_env_path" development: path: "dev_env_path" ``` ### parseLocals Parse current directory and all subdirectories, then searches for all files with `*.env.*` naming; Creates `map[K]map[string]any` object where: - K -- environment variables file name, f.e. `./docker/.env.prod` --> `.env.prod` ## Environments: DEFAULT_CONFIG = `aevs.yaml` ## Types ```golang type Project struct { Id uuid.UUID `json:"id"` Name string `json:"name"` } type State int const ( ACTIVE State = 1 INACTIVE State = -1 } type Version struct { Ts int64 `json:"ts"` // unix timestamp; Name string `json:"name"` Creator string `json:"creator"` Branch string `json:"branch"` State State `json:"state"` Envs []Env `json:"envs"` } type Env struct { Name string `json:"name"` Path string `json:"path"` } ```