diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..fbac14c1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,56 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# TypeScript and JavaScript files +# Note: Formatting rules (semicolons, trailing commas, etc.) are in .prettierrc.json +# This only sets basic editor indentation +[*.{ts,tsx,js,jsx}] +indent_style = space +indent_size = 4 + +# JSON files +# Note: Formatting rules are in .prettierrc.json +[*.json] +indent_style = space +indent_size = 4 + +# Markdown files +# Note: Formatting rules are in .prettierrc.json +[*.md] +trim_trailing_whitespace = false + +# YAML files +# Note: Prettier CAN format YAML, but it's excluded in .prettierignore +# because YAML formatting can be sensitive (e.g., Kubernetes manifests) +# If you want Prettier to format YAML, remove *.yaml and *.yml from .prettierignore +[*.{yaml,yml}] +indent_style = space +indent_size = 2 + +# Go files (Prettier doesn't format these) +[*.go] +indent_style = tab +indent_size = 4 + +# Python files (Prettier doesn't format these) +[*.py] +indent_style = space +indent_size = 4 + +# Shell scripts (Prettier doesn't format these) +[*.sh] +indent_style = space +indent_size = 4 + +# Makefile +[Makefile] +indent_style = tab diff --git a/.github/workflows/check-code-formatting.yml b/.github/workflows/check-code-formatting.yml new file mode 100644 index 00000000..cba858f8 --- /dev/null +++ b/.github/workflows/check-code-formatting.yml @@ -0,0 +1,140 @@ +name: Check Code Formatting + +on: + pull_request: + paths: + - "**.ts" + - "**.tsx" + - "**.js" + - "**.jsx" + - "**.json" + - "**.md" + - "**.py" + - "**.go" + - "**.yaml" + - "**.yml" + - ".prettierrc.json" + - ".editorconfig" + - "package.json" + - "pyproject.toml" + - ".yamllint.yml" + +jobs: + prettier: + name: Prettier (TS/JS/JSON/MD) + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "18" + cache: "npm" + + - name: Install dependencies + run: npm install + + - name: Check code formatting + run: npm run format:check + + python: + name: Ruff (Python) + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install Ruff + run: pip install ruff + + - name: Check Python formatting + run: ruff format --check secrets-manager session-manager training-portal lookup-service tunnel-manager + + - name: Check Python linting + run: ruff check secrets-manager session-manager training-portal lookup-service tunnel-manager + + golang: + name: gofmt (Go) + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: "go.work" + + - name: Check Go formatting + run: | + unformatted=$(gofmt -l assets-server/ client-programs/ tunnel-manager/) + if [ -n "$unformatted" ]; then + echo "Go files need formatting:" + echo "$unformatted" + exit 1 + fi + + yamllint: + name: yamllint (YAML) + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install yamllint + run: pip install yamllint + + - name: Lint YAML files + run: yamllint -c .yamllint.yml . + + comment-on-failure: + name: Comment on PR + runs-on: ubuntu-latest + needs: [prettier, python, golang, yamllint] + if: failure() + + steps: + - name: Comment PR if formatting is incorrect + uses: actions/github-script@v7 + with: + script: | + const body = [ + '**Code formatting check failed**', + '', + 'This PR contains files that are not formatted according to the project style.', + '', + 'To fix formatting issues, run:', + '```bash', + 'make format # Format all code (Prettier + Ruff + gofmt)', + 'make format-check # Check all formatting without modifying files', + '```', + '', + 'Or run individual formatters:', + '- `make format-prettier` — TypeScript/JavaScript/JSON/Markdown', + '- `make format-python` — Python (Ruff)', + '- `make format-go` — Go (gofmt)', + '- `make format-check-yaml` — YAML lint check', + ].join('\n'); + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body + }) diff --git a/.gitignore b/.gitignore index 5a532bac..40a7df0b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,7 @@ vendor # AI Assistant specific files .cursor + +# Root level Node.js files (for formatting tools only) +/node_modules +/package-lock.json diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..856ef37a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,32 @@ +# Dependencies +node_modules/ +**/node_modules/ + +# Build outputs +build/ +dist/ +*.tsbuildinfo + +# Generated files +**/generated/ +**/*.generated.* + +# Lock files +package-lock.json +yarn.lock +pnpm-lock.yaml + +# Go files (not formatted by Prettier) +*.go + +# Python files (not formatted by Prettier) +*.py + +# YAML files (can be formatted but may have specific formatting requirements) +*.yaml +*.yml + +# Other +.git/ +.vscode/ +.idea/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..f8f8c8a9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,22 @@ +{ + "semi": false, + "trailingComma": "all", + "singleQuote": false, + "printWidth": 120, + "tabWidth": 4, + "useTabs": false, + "arrowParens": "always", + "endOfLine": "lf", + "bracketSpacing": true, + "bracketSameLine": false, + "proseWrap": "preserve", + "overrides": [ + { + "files": "*.md", + "options": { + "printWidth": 80, + "proseWrap": "always" + } + } + ] +} diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 00000000..b7f5fa42 --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,52 @@ +--- +# yamllint configuration +# +# Relaxed rules to accommodate ytt templates, Kubernetes manifests, and +# Carvel tooling annotations (e.g. #@ directives) used throughout this project. +# +extends: default + +rules: + # Disabled: many K8s CRDs and ytt templates have very long lines + line-length: disable + # Relaxed: ytt templates and K8s manifests use varying indentation styles + indentation: disable + # Allow on/off/yes/no used in K8s manifests + truthy: + allowed-values: ["true", "false", "yes", "no", "on", "off"] + check-keys: false + # Disabled: ytt #@ directives are flagged as comments without space + comments: disable + comments-indentation: disable + # Disabled: not all YAML files start with --- + document-start: disable + # Disabled: existing files have varying whitespace conventions + trailing-spaces: disable + new-line-at-end-of-file: disable + empty-lines: disable + # Disabled: ytt templates use conditional blocks that appear as duplicate keys + key-duplicates: disable + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 1 + # Relaxed: ytt overlay files use specific spacing conventions + colons: + max-spaces-after: -1 + commas: + min-spaces-after: 0 + +ignore: + - node_modules/ + - .git/ + - build/ + - dist/ + - venv/ + - .venv/ + - "**/node_modules/" + - "**/_build/" + - "*.lock.yml" + # Go template YAML files contain {{ }} which breaks YAML parsing + - "client-programs/pkg/templates/" diff --git a/Makefile b/Makefile index 544f86a9..ad7e248f 100644 --- a/Makefile +++ b/Makefile @@ -418,4 +418,39 @@ clean-buildx: ## Clean up builder # Multiarch utility targets list-platforms: ## List available platforms for multiarch builds - @echo "Supported platforms: $(MULTIARCH_PLATFORMS)" \ No newline at end of file + @echo "Supported platforms: $(MULTIARCH_PLATFORMS)" + +# ============================================================================= +# CODE FORMATTING +# ============================================================================= + +PYTHON_DIRS = secrets-manager session-manager training-portal lookup-service tunnel-manager +GO_DIRS = assets-server/ client-programs/ tunnel-manager/ + +format: format-prettier format-python format-go ## Format all code + @echo "All formatting complete." + +format-check: format-check-prettier format-check-python format-check-go format-check-yaml ## Check all formatting + @echo "All formatting checks passed." + +format-prettier: ## Format TypeScript/JavaScript/JSON/Markdown with Prettier + npm run format + +format-check-prettier: ## Check TypeScript/JavaScript/JSON/Markdown formatting + npm run format:check + +format-python: ## Format Python code with Ruff + ruff format $(PYTHON_DIRS) + +format-check-python: ## Check Python code formatting and linting + ruff format --check $(PYTHON_DIRS) + ruff check $(PYTHON_DIRS) + +format-go: ## Format Go code with gofmt + gofmt -w $(GO_DIRS) + +format-check-go: ## Check Go code formatting + @test -z "$$(gofmt -l $(GO_DIRS))" || (echo "Go files need formatting:"; gofmt -l $(GO_DIRS); exit 1) + +format-check-yaml: ## Lint YAML files with yamllint + yamllint -c .yamllint.yml . \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..96fe42e8 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "educates-training-platform", + "version": "0.0.0", + "private": true, + "description": "Root package.json for code formatting and linting tools", + "scripts": { + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", + "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"", + "format:gateway": "prettier --write \"workshop-images/base-environment/opt/gateway/**/*.{ts,tsx,js,jsx}\"", + "format:renderer": "prettier --write \"workshop-images/base-environment/opt/renderer/**/*.{ts,tsx,js,jsx}\"", + "format:helper": "prettier --write \"workshop-images/base-environment/opt/helper/**/*.{ts,tsx,js,jsx}\"", + "format:docker-extension": "prettier --write \"docker-extension/**/*.{ts,tsx,js,jsx}\"" + }, + "devDependencies": { + "prettier": "^3.2.5" + }, + "engines": { + "node": ">=16.0.0" + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..c8cd2d64 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,35 @@ +[tool.ruff] +target-version = "py312" +line-length = 120 +exclude = [ + "venv", + ".venv", + "__pycache__", + "*.egg-info", + "build", + "dist", + "node_modules", + "project-docs/conf.py", + "**/migrations/**", +] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +line-ending = "lf" + +[tool.ruff.lint] +select = ["E", "F", "I"] +ignore = [ + "E501", # Line too long — handled by formatter + "E402", # Module level import not at top — common in Django settings + "E713", # Test for membership should be 'not in x' — existing style + "E721", # Do not compare types, use isinstance() — existing pattern + "F401", # Unused import — many intentional re-exports in __init__.py + "F403", # Wildcard import — used deliberately in some modules + "F811", # Redefinition of unused name — kopf handler patterns + "F841", # Local variable assigned but never used — may be intentional +] + +[tool.ruff.lint.isort] +known-first-party = ["project", "handlers"]