Skip to content

Commit

Permalink
feat: slim project config (#246)
Browse files Browse the repository at this point in the history
* slim project config

---------

Signed-off-by: Dennis Meister <dennis.meister@bosch.com>
  • Loading branch information
dennismeister93 authored May 3, 2024
1 parent 1e19b14 commit 1383f3d
Show file tree
Hide file tree
Showing 49 changed files with 1,457 additions and 629 deletions.
23 changes: 10 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,27 +67,24 @@ An exemplary project configuration (`.velocitas.json`) looks like this:

```json
{
"packages": [
{
"repo": "package-A",
"version": "v1.0.0"
},
{
"repo": "package-B",
"version": "v2.3.1-dev"
}
],
"packages": {
"package-A": "v1.0.0",
"package-B": "v2.3.1-dev"
},
"components": [ "component-A", "component-B" ],
"variables": {
"repoUrl": "https://github.com/eclipse-velocitas/cli",
"copyrightYear": 2023,
"autoGenerateVehicleModel": true
"autoGenerateVehicleModel": true,
"variableA@package-A": "variableA",
"variableB@component-B": "variableB",
}
}
```

As mentioned previously, a package simply is a git repository. The `repo` attribute of a package is used to identify the git repository which holds the package. `repo` is currently resolved to `https://github.com/eclipse-velocitas/<name>`. Alternatively, you can also supply a fully qualified Git repo URL e.g. `https://<your-host>/<your-repo>.git` or `git@<your-host>/<your-repo>.git`. Credentials for HTTPs and SSH based git repos are provided by your local git configuration (CLI is using Git under the hood). The `version` attribute specifies a tag, a branch or a SHA of the repository.
As mentioned previously, a package simply is a git repository. The key inside the packages is used to identify the git repository which holds the package. It is currently resolved to `https://github.com/eclipse-velocitas/<name>`. Alternatively, you can also supply a fully qualified Git repo URL e.g. `https://<your-host>/<your-repo>.git` or `git@<your-host>/<your-repo>.git`. Credentials for HTTPs and SSH based git repos are provided by your local git configuration (CLI is using Git under the hood). The value of the package attribute specifies a tag, a branch or a SHA of the repository.

The `variables` block holds user configured values for the packages and their contained components. It is a global variable definition. Should two components share the same variable name, both can be set with one line in this global block. Package-wide or component-wide variable configuration to avoid name clashes is also possible.
The `variables` block holds configured values for a specific scope (project, package or component). A variable without separator acts as a global variable. Should two components share the same variable name, both can be set with one line in this global block. Package-wide or component-wide variable configuration can be used to avoid name clashes. For a package or component scope the variable needs to be assigned with an '@' followed by either package or component ID. In the example above, `variableA@package-A` and `variableB@component-B` showcase such a usage.

Click [here](./docs/PROJECT-CONFIG.md) for an in-depth overview of the project configuration.

Expand Down
82 changes: 29 additions & 53 deletions docs/PROJECT-CONFIG.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
# Project configuration

The project configuration describes which packages your project is using and in which version. The versions of the referenced packages can be upgraded using the `upgrade` command. If you only want to see which new versions are available use `upgrade --dry-run` or `upgrade --dry-run --ignore-bounds`. Each package may expose variables which need to be set from the project configuration. If multiple different packages all expose the same named variable `foo`, setting this variable once in the project configuration will pass the value to all packages.
The project configuration describes which packages your project is using and in which version. The versions of the referenced packages can be upgraded using the `upgrade` command. If you only want to see which new versions are available use `upgrade --dry-run` or `upgrade --dry-run --ignore-bounds`. Each package may expose variables which need to be set from the project configuration. If multiple different packages all expose the same named variable `foo`, setting this variable once in the project configuration will pass the value to all packages. If a package or even a component exposes a variable which is only needed within its scope it can be set with `"variableA@package-A": "variableA"`.

Read more about variables [here](./features/VARIABLES.md).

```json
{
"packages": [
{
"repo": "package-A",
"version": "v1.0.0"
},
{
"repo": "package-B",
"version": "v2.3.1-dev"
}
],
"packages": {
"package-A": "v1.0.0",
"package-B": "v2.3.1-dev"
},
"components": [ "component-A", "component-B" ],
"variables": {
"repoUrl": "https://github.com/eclipse-velocitas/cli",
"copyrightYear": 2023,
"autoGenerateVehicleModel": true
"autoGenerateVehicleModel": true,
"variableA@package-A": "variableA",
"variableB@component-B": "variableB",
}
}
```
Expand All @@ -32,24 +29,11 @@ By default, all components of a package will be used, but if desired the used co

```json
{
"packages": [
{
"repo": "package-A",
"version": "v1.0.0"
},
{
"repo": "package-B",
"version": "v2.3.1-dev"
}
],
"components": [
{
"id": "component-exposed-by-pkg-a"
},
{
"id": "component-exposed-by-pkg-b"
},
],
"packages": {
"package-A": "v1.0.0",
"package-B": "v2.3.1-dev"
},
"components": [ "component-exposed-by-pkg-a", "component-exposed-by-pkg-b" ],
"variables": {
"repoUrl": "https://github.com/eclipse-velocitas/cli",
"copyrightYear": 2023,
Expand All @@ -62,23 +46,25 @@ The project above will only use the components `component-exposed-by-pkg-a` and

## File Structure

### `packages` - Array[[`PackageConfig`](#packageconfig)]
### `packages` - Map[string, string]

A key-value configuration of packages, where key is the package [repo](#repo) and value is the [version](#version).

Array of packages used in the project.
### `components` - string[]

An array of used components.

### `variables` - Map[string, any]

Project-wide key-value variable configuration.
Project-wide key-value [variable](#variables) configuration.

# Types

## `PackageConfig`

### `repo` - string
## `repo`

The name of the package or URL to the package git repository. A simple name is currently resolved to `https://github.com/eclipse-velocitas/<name>`. Alternatively, you can also supply a fully qualified Git repo URL e.g. `https://<your-host>/<your-repo>.git` or `git@<your-host>/<your-repo>.git`. Credentials for HTTPs and SSH based git repos are provided by your local git configuration (CLI is using Git under the hood).

### `version` - string
## `version`

The version of the package to use.
| Literal | Behaviour | Example |
Expand All @@ -88,20 +74,10 @@ The version of the package to use.
| branch (prefixed with an '@') | Refers to the latest commit in a specific branch | `"@main"` |
| latest | Refers to the latest tag if available else to the highest version tag | `"latest"` |

### `variables` - Map[string, any]

Package-wide variable configuration.

### `components` - Array[[`ComponentConfig`](#componentconfig)]

Per-component configuration.

## `ComponentConfig`

### `id` - string

Unique ID of the component within the package.

### `variables` - Map[string, any]
## `variables`

Component-wide key-value variable configuration
| Scope | Example |
|-------|---------|
| Global | `"projectVariable": "A project wide variable"` |
| Package | `"packageVariable@pkg-a": "A package wide variable"` |
| Component | `"componentVariable@component-exposed-by-pkg-a": "A component wide variable"` |
4 changes: 2 additions & 2 deletions src/commands/cache/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import { Command } from '@oclif/core';
import { ProjectCache } from '../../modules/project-cache';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class Clear extends Command {
static description = "Clean a project's cache.";
Expand All @@ -26,7 +26,7 @@ export default class Clear extends Command {

// although we are not reading the project config, we want to
// ensure the command is run in a project directory only.
ProjectConfig.read(`v${this.config.version}`);
ProjectConfigIO.read(`v${this.config.version}`);
const cache = ProjectCache.read();
cache.clear();
cache.write();
Expand Down
4 changes: 2 additions & 2 deletions src/commands/cache/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import { Args, Command } from '@oclif/core';
import { mapReplacer } from '../../modules/helpers';
import { ProjectCache } from '../../modules/project-cache';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class Get extends Command {
static description = 'Get the complete cache contents as JSON string or the value of a single key.';
Expand All @@ -36,7 +36,7 @@ bar`,

// although we are not reading the project config, we want to
// ensure the command is run in a project directory only.
ProjectConfig.read(`v${this.config.version}`);
ProjectConfigIO.read(`v${this.config.version}`);

const cache = ProjectCache.read();

Expand Down
4 changes: 2 additions & 2 deletions src/commands/cache/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import { Args, Command } from '@oclif/core';
import { ProjectCache } from '../../modules/project-cache';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class Set extends Command {
static description = 'Set the cache value of an entry.';
Expand All @@ -31,7 +31,7 @@ export default class Set extends Command {

// although we are not reading the project config, we want to
// ensure the command is run in a project directory only.
ProjectConfig.read(`v${this.config.version}`);
ProjectConfigIO.read(`v${this.config.version}`);

const cache = ProjectCache.read();
cache.set(args.key, args.value);
Expand Down
11 changes: 7 additions & 4 deletions src/commands/component/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// SPDX-License-Identifier: Apache-2.0

import { Args, Command } from '@oclif/core';
import { ProjectConfig } from '../../modules/project-config';
import { ComponentContext } from '../../modules/component';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class Add extends Command {
static description = 'Add project components.';
Expand All @@ -27,8 +28,10 @@ export default class Add extends Command {
async run(): Promise<void> {
const { args } = await this.parse(Add);

const projectConfig = ProjectConfig.read(`v${this.config.version}`);
const foundComponent = projectConfig.getComponents(false).find((compContext) => compContext.manifest.id === args.id);
const projectConfig = ProjectConfigIO.read(`v${this.config.version}`);
const foundComponent = projectConfig
.getComponentContexts(false)
.find((compContext: ComponentContext) => compContext.manifest.id === args.id);

if (!foundComponent) {
throw Error(
Expand All @@ -41,6 +44,6 @@ export default class Add extends Command {
}

projectConfig.addComponent(foundComponent?.manifest.id);
projectConfig.write();
ProjectConfigIO.write(projectConfig);
}
}
6 changes: 3 additions & 3 deletions src/commands/component/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// SPDX-License-Identifier: Apache-2.0

import { Command, Flags } from '@oclif/core';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class List extends Command {
static description = 'List project components.';
Expand All @@ -35,10 +35,10 @@ export default class List extends Command {
async run(): Promise<void> {
const { flags } = await this.parse(List);

const projectConfig = ProjectConfig.read(`v${this.config.version}`);
const projectConfig = ProjectConfigIO.read(`v${this.config.version}`);
const onlyUsed = !flags.all && !flags.unused;

for (const componentContext of projectConfig.getComponents(onlyUsed)) {
for (const componentContext of projectConfig.getComponentContexts(onlyUsed)) {
if (flags.unused && componentContext.usedInProject) {
continue;
}
Expand Down
10 changes: 5 additions & 5 deletions src/commands/component/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@
// SPDX-License-Identifier: Apache-2.0

import { Args, Command } from '@oclif/core';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';

export default class Remove extends Command {
static description = 'Remove project components.';

static examples = [`$ velocitas component remove <id>`];

static args = {
id: Args.string({ description: 'ID of the component to add', required: true }),
id: Args.string({ description: 'ID of the component to remove', required: true }),
};

async run(): Promise<void> {
const { args } = await this.parse(Remove);

const projectConfig = ProjectConfig.read(`v${this.config.version}`);
const projectConfig = ProjectConfigIO.read(`v${this.config.version}`);

const foundComponent = projectConfig.getComponents(false).find((compContext) => compContext.manifest.id === args.id);
const foundComponent = projectConfig.getComponentContexts(false).find((compContext) => compContext.manifest.id === args.id);

if (!foundComponent) {
throw Error(
Expand All @@ -42,6 +42,6 @@ export default class Remove extends Command {
}

projectConfig.removeComponent(foundComponent?.manifest.id);
projectConfig.write();
ProjectConfigIO.write(projectConfig);
}
}
7 changes: 5 additions & 2 deletions src/commands/create/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import { Command, Flags } from '@oclif/core';
import { AppManifest, AppManifestInterfaceAttributes } from '../../modules/app-manifest';
import { InteractiveMode } from '../../modules/create-interactive';
import { CoreComponent, CoreOptions, DescribedId, ExtensionComponent, PackageIndex, Parameter } from '../../modules/package-index';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfig } from '../../modules/projectConfig/projectConfig';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';
// eslint-disable-next-line @typescript-eslint/naming-convention
import Exec from '../exec';
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down Expand Up @@ -228,7 +229,9 @@ export default class Create extends Command {
} else {
createData = await this._parseFlags(packageIndex, flags);
}
await ProjectConfig.create(createData.componentIds, packageIndex, this.config.version);
const projectConfig = await ProjectConfig.create(createData.componentIds, packageIndex, this.config.version);
ProjectConfigIO.write(projectConfig);

createData.appManifest.write();

this.log(`... Project for Vehicle Application '${createData.name}' created!`);
Expand Down
4 changes: 2 additions & 2 deletions src/commands/exec/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Args, Command, Flags } from '@oclif/core';
import { APP_MANIFEST_PATH_VARIABLE, AppManifest } from '../../modules/app-manifest';
import { ExecSpec } from '../../modules/component';
import { ExecExitError, runExecSpec } from '../../modules/exec';
import { ProjectConfig } from '../../modules/project-config';
import { ProjectConfigIO } from '../../modules/projectConfig/projectConfigIO';
import { createEnvVars } from '../../modules/variables';

export default class Exec extends Command {
Expand Down Expand Up @@ -75,7 +75,7 @@ export default class Exec extends Command {
const programArgsAndFlags = this._extractProgramArgsAndFlags();
const { args, flags } = await this.parse(Exec);

const projectConfig = ProjectConfig.read(`v${this.config.version}`);
const projectConfig = ProjectConfigIO.read(`v${this.config.version}`);

const execSpec: ExecSpec = {
ref: args.ref,
Expand Down
Loading

0 comments on commit 1383f3d

Please sign in to comment.