diff --git a/.github/workflows/be-installation-test.yml b/.github/workflows/be-installation-test.yml new file mode 100644 index 0000000..4492c91 --- /dev/null +++ b/.github/workflows/be-installation-test.yml @@ -0,0 +1,57 @@ +name: Test backend installation + +on: + pull_request: + branches: + - develop + - main + paths: + - '**.py' + - '**.txt' + - '**/pyproject.toml' + - '**/uv.lock' + workflow_dispatch: + +permissions: + checks: read + contents: read + +jobs: + installation-backend: + name: Test backend installation + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v5 + + - name: Set up Python environment + uses: actions/setup-python@v6 + with: + python-version: "3.11" + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version: "latest" + enable-cache: true + + - name: Install dependencies + run: uv sync --locked --all-extras --dev --project backend-agent + + - name: Start server and check health + working-directory: backend-agent + run: | + DISABLE_AGENT=1 DB_PATH=${RUNNER_TEMP}/data.db uv run main.py > server.log 2>&1 & + for i in {1..20}; do + sleep 1 + status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health || true) + if [ "$status" -eq 200 ]; then + echo "Health check succeeded" + cat server.log + exit 0 + fi + done + echo "Health check failed after waiting" + cat server.log + exit 1 diff --git a/.github/workflows/fe-installation-test.yml b/.github/workflows/fe-installation-test.yml new file mode 100644 index 0000000..4b57c26 --- /dev/null +++ b/.github/workflows/fe-installation-test.yml @@ -0,0 +1,73 @@ +name: Test frontend installation + +on: + pull_request: + branches: + - develop + - main + paths: + - 'frontend/package*.json' + - 'frontend/**.ts' + - 'frontend/**.js' + - 'frontend/**.json' + - 'frontend/**.css' + - 'frontend/**.html' + workflow_dispatch: + +permissions: + checks: read + contents: read + +jobs: + installation-frontend: + name: Test frontend installation + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v5 + + - name: Set up Node.js environment + uses: actions/setup-node@v5 + with: + node-version: "24" + + - name: Install dependencies + working-directory: frontend + run: npm ci + + - name: Build frontend + working-directory: frontend + run: npm run build + + - name: Verify build artifacts + working-directory: frontend + run: | + if [ -d "dist/" ]; then + echo "Build artifacts found in dist/" + ls -la dist/ + else + echo "Build artifacts not found" + exit 1 + fi + + - name: Test dev server startup + working-directory: frontend + timeout-minutes: 2 + run: | + # Start the dev server in background + npm start & + DEV_SERVER_PID=$! + + # Wait for server to be ready (max 60 seconds) + for i in {1..60}; do + sleep 1 + if curl -f -s http://localhost:4200 > /dev/null 2>&1; then + echo "Dev server started successfully" + kill $DEV_SERVER_PID + exit 0 + fi + done + + echo "Dev server failed to start within 60 seconds" + kill $DEV_SERVER_PID + exit 1 \ No newline at end of file diff --git a/.github/workflows/installation-test.yml b/.github/workflows/installation-test.yml deleted file mode 100644 index ca117f0..0000000 --- a/.github/workflows/installation-test.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Test backend installation - -on: - pull_request: - branches: - - develop - - main - paths: - - '**.py' - - '**.txt' - workflow_dispatch: - -permissions: - checks: read - contents: read - -jobs: - installation: - name: Test backend installation - runs-on: ubuntu-latest - steps: - - name: Check out Git repository - uses: actions/checkout@v5 - - - name: Set up Python environment - uses: actions/setup-python@v6 - with: - python-version: "3.11" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install uv - uses: astral-sh/setup-uv@v6 - with: - version: "latest" - enable-cache: true - - - name: Install dependencies - run: uv sync --locked --all-extras --dev --project backend-agent - - - name: Start server and check health - working-directory: backend-agent - run: | - DISABLE_AGENT=1 DB_PATH=${RUNNER_TEMP}/data.db uv run main.py > server.log 2>&1 & - for i in {1..20}; do - sleep 1 - status=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health || true) - if [ "$status" -eq 200 ]; then - echo "Health check succeeded" - cat server.log - exit 0 - fi - done - echo "Health check failed after waiting" - cat server.log - exit 1 diff --git a/.github/workflows/lint-backend.yml b/.github/workflows/lint-backend.yml index bb5f335..c1d13a6 100644 --- a/.github/workflows/lint-backend.yml +++ b/.github/workflows/lint-backend.yml @@ -7,6 +7,7 @@ on: - main paths: - '**.py' + - 'CHANGELOG.md' workflow_dispatch: permissions: diff --git a/.github/workflows/lint-frontend.yml b/.github/workflows/lint-frontend.yml index cb7f59f..6bdf6ce 100644 --- a/.github/workflows/lint-frontend.yml +++ b/.github/workflows/lint-frontend.yml @@ -6,9 +6,10 @@ on: - develop - main paths: - - '**.json' - '**.ts' - '**.js' + - '**/package.json' + - 'CHANGELOG.md' workflow_dispatch: permissions: @@ -33,8 +34,8 @@ jobs: node-version: 24 - name: Install Node.js dependencies + working-directory: frontend run: | - cd frontend npm ci - name: Run linters @@ -42,6 +43,6 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} reporter: github-pr-review + workdir: frontend eslint_flags: "--format rdjson --ext .js,.jsx,.ts,.tsx ./" fail_level: error - workdir: frontend diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json deleted file mode 100644 index 57a8875..0000000 --- a/frontend/.eslintrc.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "root": true, - "ignorePatterns": [ - "projects/**/*" - ], - "overrides": [ - { - "files": [ - "*.ts" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@angular-eslint/recommended", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "app", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "app", - "style": "kebab-case" - } - ], - "semi": 2 - } - }, - { - "files": [ - "*.html" - ], - "extends": [ - "plugin:@angular-eslint/template/recommended", - "plugin:@angular-eslint/template/accessibility" - ], - "rules": {} - } - ] -} diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs new file mode 100644 index 0000000..ec5a4bd --- /dev/null +++ b/frontend/eslint.config.mjs @@ -0,0 +1,49 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default defineConfig([globalIgnores(["projects/**/*"]), { + files: ["**/*.ts"], + + extends: compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates", + ), + + rules: { + "@angular-eslint/directive-selector": ["error", { + type: "attribute", + prefix: "app", + style: "camelCase", + }], + + "@angular-eslint/component-selector": ["error", { + type: "element", + prefix: "app", + style: "kebab-case", + }], + + semi: 2, + }, +}, { + files: ["**/*.html"], + + extends: compat.extends( + "plugin:@angular-eslint/template/recommended", + "plugin:@angular-eslint/template/accessibility", + ), + + rules: {}, +}]); \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f725de4..744d8b9 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -19,6 +19,7 @@ "@angular/platform-browser-dynamic": "^20.2.4", "@angular/router": "^20.2.4", "apexcharts": "^5.3.5", + "marked": "^16.3.0", "ng-apexcharts": "^2.0.1", "ngx-markdown": "^20.1.0", "rxjs": "^7.8.2", @@ -13628,16 +13629,15 @@ } }, "node_modules/marked": { - "version": "15.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz", - "integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.3.0.tgz", + "integrity": "sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==", "license": "MIT", - "peer": true, "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 18" + "node": ">= 20" } }, "node_modules/math-intrinsics": { @@ -13741,19 +13741,6 @@ "uuid": "^11.1.0" } }, - "node_modules/mermaid/node_modules/marked": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-16.2.0.tgz", - "integrity": "sha512-LbbTuye+0dWRz2TS9KJ7wsnD4KAtpj0MVkWc90XvBa6AslXsT0hTBVH5k32pcSyHH1fst9XEFJunXHktVy0zlg==", - "license": "MIT", - "optional": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",