diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index dfdd0e3..cb8f737 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -28,7 +28,7 @@ jobs: TEMPLATE_NAME=$(basename "$dir") COMPOSE_FILE="$dir/docker-compose.yml" - TEMPLATE_FILE="$dir/template.yml" + TEMPLATE_FILE="$dir/template.toml" if [ ! -f "$COMPOSE_FILE" ]; then echo "❌ Missing docker-compose.yml in $TEMPLATE_NAME" @@ -36,7 +36,7 @@ jobs: fi if [ ! -f "$TEMPLATE_FILE" ]; then - echo "❌ Missing template.yml in $TEMPLATE_NAME" + echo "❌ Missing template.toml in $TEMPLATE_NAME" ERROR=1 fi fi diff --git a/README.md b/README.md index 10ecec7..01fe605 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ services: volumes: grafana-storage: {} ``` -3. Add the `template.yml` file to the folder, this is where we specify the domains, mounts and env variables, to understand more the structure of `template.yml` you can read here [Template.yml structure](#templateyml-structure) +3. Add the `template.toml` file to the folder, this is where we specify the domains, mounts and env variables, to understand more the structure of `template.toml` you can read here [Template.toml structure](#template.toml-structure) ```yaml variables: @@ -82,48 +82,50 @@ config: 6. Commit and push your changes 7. Create a pull request -### Template.yml structure - -Dokploy use a defined structure for the `template.yml` file, we have 4 sections available: +### Template.toml structure +Dokploy use a defined structure for the `template.toml` file, we have 4 sections available: 1. `variables`: This is where we define the variables that will be used in the `domains`, `env` and `mounts` sections. 2. `domains`: This is where we define the configuration for the template. 3. `env`: This is where we define the environment variables for the template. 4. `mounts`: This is where we define the mounts for the template. - - The `variables(Optional)` structure is the following: -```yaml -variables: - main_domain: ${domain} - my_domain: https://my-domain.com - my_password: ${password:32} - any_helper: ${you-can-use-any-helper} +```toml +[variables] +main_domain = "${domain}" +my_domain = "https://my-domain.com" +my_password = "${password:32}" +any_helper = "${you-can-use-any-helper}" ``` - The `config` structure is the following: -```yaml -config: - domains: # Optional - - serviceName: grafana # Required - port: 3000 # Required - host: ${main_domain} # Required - path: / # Optional +```toml +[config] +# Optional sections below - env: # Optional - - AP_HOST=${main_domain} - - AP_API_KEY=${api_key} - - AP_ENCRYPTION_KEY=${encryption_key} - - AP_JWT_SECRET=${jwt_secret} - - AP_POSTGRES_PASSWORD=${postgres_password} +[[config.domains]] +serviceName = "grafana" # Required +port = 3000 # Required +host = "${main_domain}" # Required +path = "/" # Optional - mounts: # Optional or [] - - filePath: /content/file.txt - content: | - My content +env = [ + "AP_HOST=${main_domain}", + "AP_API_KEY=${api_key}", + "AP_ENCRYPTION_KEY=${encryption_key}", + "AP_JWT_SECRET=${jwt_secret}", + "AP_POSTGRES_PASSWORD=${postgres_password}" +] + +[[config.mounts]] +filePath = "/content/file.txt" +content = """ +My content +""" ``` Important: you can reference any variable in the `domains`, `env` and `mounts` sections. just use the `${variable_name}` syntax, in the case you don't want to define a variable, you can use the `domain`, `base64`, `password`, `hash`, `uuid`, `randomPort` or `timestamp` helpers. diff --git a/app/package.json b/app/package.json index a0f490f..19dc0c5 100644 --- a/app/package.json +++ b/app/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "yaml":"2.7.1", + "@iarna/toml": "^2.2.5", "@codemirror/autocomplete": "^6.18.6", "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-yaml": "^6.1.1", diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index 3669f77..b73fc7d 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: '@codemirror/view': specifier: 6.29.0 version: 6.29.0 + '@iarna/toml': + specifier: ^2.2.5 + version: 2.2.5 '@radix-ui/react-dialog': specifier: ^1.1.6 version: 1.1.6(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -46,7 +49,7 @@ importers: version: 1.1.3(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tailwindcss/vite': specifier: ^4.0.12 - version: 4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)) + version: 4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) '@uiw/codemirror-theme-github': specifier: ^4.22.1 version: 4.23.10(@codemirror/language@6.10.8)(@codemirror/state@6.5.2)(@codemirror/view@6.29.0) @@ -91,7 +94,10 @@ importers: version: 1.0.7(tailwindcss@4.0.12) vite-plugin-static-copy: specifier: 2.3.0 - version: 2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)) + version: 2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) + yaml: + specifier: 2.7.1 + version: 2.7.1 zustand: specifier: ^5.0.3 version: 5.0.3(@types/react@19.0.10)(react@19.0.0) @@ -107,7 +113,7 @@ importers: version: 19.0.4(@types/react@19.0.10) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)) + version: 4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)) globals: specifier: ^15.15.0 version: 15.15.0 @@ -116,7 +122,7 @@ importers: version: 5.7.3 vite: specifier: ^6.2.0 - version: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2) + version: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) packages: @@ -408,6 +414,9 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@iarna/toml@2.2.5': + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -1657,6 +1666,11 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yaml@2.7.1: + resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==} + engines: {node: '>= 14'} + hasBin: true + zustand@5.0.3: resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} engines: {node: '>=12.20.0'} @@ -1965,6 +1979,8 @@ snapshots: '@floating-ui/utils@0.2.9': {} + '@iarna/toml@2.2.5': {} + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -2581,13 +2597,13 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.0.12 '@tailwindcss/oxide-win32-x64-msvc': 4.0.12 - '@tailwindcss/vite@4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2))': + '@tailwindcss/vite@4.0.12(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1))': dependencies: '@tailwindcss/node': 4.0.12 '@tailwindcss/oxide': 4.0.12 lightningcss: 1.29.2 tailwindcss: 4.0.12 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2) + vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) '@types/babel__core@7.20.5': dependencies: @@ -2665,14 +2681,14 @@ snapshots: - '@codemirror/lint' - '@codemirror/search' - '@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2))': + '@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1))': dependencies: '@babel/core': 7.26.9 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2) + vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) transitivePeerDependencies: - supports-color @@ -3087,16 +3103,16 @@ snapshots: optionalDependencies: '@types/react': 19.0.10 - vite-plugin-static-copy@2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)): + vite-plugin-static-copy@2.3.0(vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1)): dependencies: chokidar: 3.6.0 fast-glob: 3.3.3 fs-extra: 11.3.0 p-map: 7.0.3 picocolors: 1.1.1 - vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2) + vite: 6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) - vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2): + vite@6.2.1(@types/node@20.17.24)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1): dependencies: esbuild: 0.25.1 postcss: 8.5.3 @@ -3106,11 +3122,14 @@ snapshots: fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.29.2 + yaml: 2.7.1 w3c-keyname@2.2.8: {} yallist@3.1.1: {} + yaml@2.7.1: {} + zustand@5.0.3(@types/react@19.0.10)(react@19.0.0): optionalDependencies: '@types/react': 19.0.10 diff --git a/app/script.js b/app/script.js new file mode 100644 index 0000000..fd64000 --- /dev/null +++ b/app/script.js @@ -0,0 +1,36 @@ +import yaml from "yaml"; +import toml from "@iarna/toml"; +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +function convertYamlToToml(yamlContent) { + const parsedYaml = yaml.parse(yamlContent); + return toml.stringify(parsedYaml); +} + +function processDirectory(dirPath) { + const files = fs.readdirSync(dirPath); + + files.forEach((file) => { + const filePath = path.join(dirPath, file); + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + processDirectory(filePath); + } else if (file === "template.yml") { + console.log(`Converting ${filePath}`); + const yamlContent = fs.readFileSync(filePath, "utf8"); + const tomlContent = convertYamlToToml(yamlContent); + const tomlPath = path.join(dirPath, "template.toml"); + fs.writeFileSync(tomlPath, tomlContent); + } + }); +} + +// Ruta al directorio blueprints relativa al script +const blueprintsPath = path.join(__dirname, "..", "blueprints"); +processDirectory(blueprintsPath); diff --git a/app/src/components/TemplateDialog.tsx b/app/src/components/TemplateDialog.tsx index af7fd03..89e0893 100644 --- a/app/src/components/TemplateDialog.tsx +++ b/app/src/components/TemplateDialog.tsx @@ -228,7 +228,7 @@ const TemplateDialog: React.FC = ({