diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..fdf456442 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,22 @@ +{ + "env": { + "node": true, + "es2021": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": { + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/no-explicit-any": "warn", + "no-console": "off" + }, + "ignorePatterns": ["lib/", "node_modules/", "tabs/", "functions/"] +} diff --git a/.github/workflows/ci-quality-checks.yml b/.github/workflows/ci-quality-checks.yml new file mode 100644 index 000000000..9a079e9a9 --- /dev/null +++ b/.github/workflows/ci-quality-checks.yml @@ -0,0 +1,102 @@ +# CI workflow for code quality checks +# Runs linting, formatting validation, and type checking + +name: Code Quality Checks + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + lint-and-format-bot: + name: Lint & Format (Bot/Backend) + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run ESLint + run: npm run lint + + - name: Check Prettier formatting + run: npm run format:check + + - name: Run TypeScript type check + run: npm run typecheck + + lint-and-format-tabs: + name: Lint & Format (Frontend/Tabs) + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + cache-dependency-path: tabs/package-lock.json + + - name: Install dependencies + working-directory: tabs + run: npm ci + + - name: Run ESLint + working-directory: tabs + run: npm run lint + + - name: Check Prettier formatting + working-directory: tabs + run: npm run format:check + + - name: Run TypeScript type check + working-directory: tabs + run: npm run typecheck + + build-check: + name: Build Verification + runs-on: ubuntu-latest + needs: [lint-and-format-bot, lint-and-format-tabs] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'npm' + + - name: Install Bot dependencies + run: npm ci + + - name: Build Bot + run: npm run build + + - name: Install Tabs dependencies + working-directory: tabs + run: npm ci + + - name: Build Tabs + working-directory: tabs + env: + CI: false + run: npm run build diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..1a25b6d58 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,15 @@ +# Dependencies +node_modules/ + +# Build outputs +lib/ +build/ +dist/ + +# Tabs (has its own prettier config) +tabs/ + +# Other +*.min.js +*.min.css +package-lock.json diff --git a/README.md b/README.md index ecbd9e2ec..82137667f 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,38 @@ Zaplie integrates directly with Microsoft Teams to enhance collaboration and rec 2. Install the packages using `npm install` 3. Run the application using `npm start` +## Code Quality + +This project uses ESLint and Prettier to maintain code quality and consistent formatting. Quality checks run automatically on all pull requests to the `main` branch. + +### Available Scripts + +**Bot/Backend (root directory):** +```bash +npm run lint # Run ESLint +npm run lint:fix # Auto-fix lint issues +npm run format # Format code with Prettier +npm run format:check # Check formatting without changes +npm run typecheck # Run TypeScript type checking +``` + +**Frontend/Tabs (`tabs/` directory):** +```bash +npm run lint # Run ESLint +npm run lint:fix # Auto-fix lint issues +npm run format # Format code with Prettier +npm run format:check # Check formatting without changes +npm run typecheck # Run TypeScript type checking +``` + +### CI Pipeline + +The CI workflow (`.github/workflows/ci-quality-checks.yml`) runs on every push and PR to `main`: +1. **Linting** - ESLint checks for both bot and tabs +2. **Formatting** - Prettier validation +3. **Type Checking** - TypeScript compilation checks for both bot and tabs +4. **Build Verification** - Ensures both projects build successfully + # Get in touch Have fun, and tag us on Twitter / Nostr! diff --git a/package.json b/package.json index f8940c53a..1acf8466b 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Microsoft Teams Toolkit sso bot sample", "engines": { - "node": "16 || 18" + "node": "16 || 18 || 20" }, "author": "Microsoft", "license": "MIT", @@ -16,7 +16,12 @@ "write-env": "cross-env TEAMSFX_ENV=$TEAMSFX_ENV node scripts/writeEnv.js", "start": "node ./lib/src/index.js", "watch": "nodemon --exec \"npm run start\"", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "eslint src/ --ext .ts,.tsx", + "lint:fix": "eslint src/ --ext .ts,.tsx --fix", + "format": "prettier --write \"src/**/*.{ts,tsx,json}\"", + "format:check": "prettier --check \"src/**/*.{ts,tsx,json}\"", + "typecheck": "tsc --noEmit" }, "repository": { "type": "git", @@ -41,9 +46,13 @@ "@types/jest": "^29.5.12", "@types/node": "^14.0.0", "@types/restify": "8.5.5", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", "cross-env": "^7.0.3", "env-cmd": "^10.1.0", + "eslint": "^8.57.0", "nodemon": "^2.0.7", + "prettier": "^3.2.0", "shx": "^0.3.3", "ts-jest": "^29.2.4", "ts-node": "^10.4.0", diff --git a/tabs/.prettierignore b/tabs/.prettierignore new file mode 100644 index 000000000..547a442cd --- /dev/null +++ b/tabs/.prettierignore @@ -0,0 +1,10 @@ +# Dependencies +node_modules/ + +# Build outputs +build/ + +# Other +*.min.js +*.min.css +package-lock.json diff --git a/tabs/.prettierrc b/tabs/.prettierrc new file mode 100644 index 000000000..6d55a7a77 --- /dev/null +++ b/tabs/.prettierrc @@ -0,0 +1,10 @@ +{ + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "bracketSpacing": true, + "arrowParens": "avoid", + "printWidth": 80 +} diff --git a/tabs/package.json b/tabs/package.json index b6b6ce3ff..9551522f4 100644 --- a/tabs/package.json +++ b/tabs/package.json @@ -38,7 +38,12 @@ "client": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "lint": "eslint src/ --ext .js,.jsx,.ts,.tsx", + "lint:fix": "eslint src/ --ext .js,.jsx,.ts,.tsx --fix", + "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css}\"", + "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,json,css}\"", + "typecheck": "tsc --noEmit" }, "eslintConfig": { "extends": [ @@ -66,6 +71,7 @@ "@types/react-dom": "^18.3.0", "@types/react-qr-reader": "^2.1.7", "concurrently": "^9.1.2", + "prettier": "^3.2.0", "ts-loader": "^9.5.1", "typescript": "^4.9.5" }