From 9707542b9568c29f36cc7db96e0a4529c35f255e Mon Sep 17 00:00:00 2001 From: Nicolas Meienberger <47644445+meienberger@users.noreply.github.com> Date: Sun, 19 May 2024 13:41:35 +0200 Subject: [PATCH] Feat/docker compose json (#3503) * feat(2fauth): a docker-compose.json config * ci(app-version): increase image automatically in docker-compose.json --- .eslintrc.js | 10 ++++- .github/workflows/renovate-app-version.sh | 49 ++++++++++++++++------- .prettierrc | 1 - .prettierrc.js | 7 ++++ apps/2fauth/config.json | 10 ++--- apps/2fauth/docker-compose.json | 20 +++++++++ apps/__tests__/app-config.ts | 32 +++++++++++++++ 7 files changed, 104 insertions(+), 25 deletions(-) delete mode 100644 .prettierrc create mode 100644 .prettierrc.js create mode 100644 apps/2fauth/docker-compose.json create mode 100644 apps/__tests__/app-config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 02c672f1..3153841e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,13 @@ module.exports = { - extends: ["plugin:json-schema-validator/recommended"], + extends: ['plugin:json-schema-validator/recommended'], plugins: [], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, rules: { - "json-schema-validator/no-invalid": "error", + 'json-schema-validator/no-invalid': 'error', }, }; diff --git a/.github/workflows/renovate-app-version.sh b/.github/workflows/renovate-app-version.sh index fa6764f5..0ceefe27 100755 --- a/.github/workflows/renovate-app-version.sh +++ b/.github/workflows/renovate-app-version.sh @@ -4,14 +4,14 @@ app_name=$1 # find all docker-compose files under apps/$app_name (there should be only one) -docker_compose_files=$(find apps/$app_name -name docker-compose.yml) +docker_compose_files=$(find apps/"$app_name" -name docker-compose.yml) for docker_compose_file in $docker_compose_files do # Assuming that the app version will be from the first docker image - first_service=$(yq '.services | keys | .[0]' $docker_compose_file) + first_service=$(yq '.services | keys | .[0]' "$docker_compose_file") - image=$(yq .services.$first_service.image $docker_compose_file) + image=$(yq .services."$first_service".image "$docker_compose_file") # Only apply changes if the format is : if [[ "$image" == *":"* ]]; then @@ -20,20 +20,39 @@ do # Trim the "v" prefix trimmed_version=${version/#"v"} - # Find config file + # ------------------- Update config.json ------------------- config_file=${docker_compose_file/docker-compose.yml/config.json} - current_config_version=$(jq -r '.version' $config_file) + current_config_version=$(jq -r '.version' "$config_file") + echo "Current config version: $current_config_version" - # Update the version in config.json, but only if there's a change - if [[ "$current_config_version" != "$trimmed_version" ]]; then - contents="$(jq --arg trimmed_version "$trimmed_version" '.version=$trimmed_version' $config_file)" - echo "${contents}" > $config_file + # Update the version in config.json + contents="$(jq --arg trimmed_version "$trimmed_version" '.version=$trimmed_version' "$config_file")" + echo "${contents}" > "$config_file" - tipi_version=$(jq -r '.tipi_version' $config_file) - tipi_version=$((tipi_version + 1)) - contents="$(jq --argjson tipi_version $tipi_version '.tipi_version=$tipi_version' $config_file)" - echo "${contents}" > $config_file - fi + + # ------------------- Update docker-compose.json ------------------- + # Update the version in docker-compose.json if it exists + if [[ -f ${docker_compose_file/docker-compose.yml/docker-compose.json} ]]; then + compose_file=${docker_compose_file/docker-compose.yml/docker-compose.json} + + echo "Updating $compose_file with version $image" + + main_service_index=$(yq '.services | to_entries[] | select(.value.isMain == true) | .key' "$compose_file") + + # apply trimmed version to docker-compose.json's main service + contents="$(jq --arg image "$image" --arg main_service_index "$main_service_index" '.services[$main_service_index | tonumber].image=$image' "$compose_file")" + echo "${contents}" > "$compose_file" + fi + + # ------------------- Update config.json ------------------- + tipi_version=$(jq -r '.tipi_version' "$config_file") + tipi_version=$((tipi_version + 1)) + contents="$(jq --argjson tipi_version $tipi_version '.tipi_version=$tipi_version' "$config_file")" + echo "${contents}" > "$config_file" + + # ------------------- Format files with prettier ------------------- + npx prettier "$config_file" --write + npx prettier "$compose_file" --write fi -done \ No newline at end of file +done diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 0967ef42..00000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..a317a88d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + singleQuote: true, + semi: true, + trailingComma: "all", + tabWidth: 2, + printWidth: 150, +}; diff --git a/apps/2fauth/config.json b/apps/2fauth/config.json index 244d710d..a8bf7121 100644 --- a/apps/2fauth/config.json +++ b/apps/2fauth/config.json @@ -6,20 +6,16 @@ "gid": 1000, "available": true, "exposable": true, + "dynamic_config": true, "id": "2fauth", "tipi_version": 15, "version": "5.1.1", - "categories": [ - "security" - ], + "categories": ["security"], "description": "A Web app to manage your Two-Factor Authentication (2FA) accounts and generate their security codes.", "short_desc": "Manage your Two-Factor Authentication codes.", "author": "Bubka", "source": "https://github.com/Bubka/2FAuth", "website": "https://docs.2fauth.app/", "form_fields": [], - "supported_architectures": [ - "arm64", - "amd64" - ] + "supported_architectures": ["arm64", "amd64"] } diff --git a/apps/2fauth/docker-compose.json b/apps/2fauth/docker-compose.json new file mode 100644 index 00000000..f5129af6 --- /dev/null +++ b/apps/2fauth/docker-compose.json @@ -0,0 +1,20 @@ +{ + "services": [ + { + "name": "2fauth", + "image": "2fauth/2fauth:5.1.1", + "internalPort": 8000, + "isMain": true, + "volumes": [ + { + "hostPath": "${APP_DATA_DIR}/data", + "containerPath": "/2fauth" + } + ], + "environment": { + "ASSET_URL": "https://${APP_DOMAIN}", + "APP_URL": "https://${APP_DOMAIN}" + } + } + ] +} diff --git a/apps/__tests__/app-config.ts b/apps/__tests__/app-config.ts new file mode 100644 index 00000000..56d0afc0 --- /dev/null +++ b/apps/__tests__/app-config.ts @@ -0,0 +1,32 @@ +import { z } from 'zod'; + +export const appConfigSchema = z.object({ + services: z.array( + z.object({ + name: z.string(), + image: z.string(), + internalPort: z.number().min(1).max(65535), + isMain: z.boolean().optional(), + command: z.string().optional(), + // eg: /path/to/volume:/path/in/container + volumes: z.array( + z.object({ + hostPath: z.string().regex(/^\/.+/), + containerPath: z.string().regex(/^\/.+/), + }), + ), + environment: z.record(z.string()).optional(), + healthCheck: z + .object({ + test: z.string(), + // eg: 5s, 1m, 1h + interval: z.string().regex(/^\d+[smh]$/), + timeout: z.string().regex(/^\d+[smh]$/), + retries: z.number().min(0), + }) + .optional(), + }), + ), +}); + +export type AppConfig = z.input;