diff --git a/CI_CD_SETUP.md b/CI_CD_SETUP.md new file mode 100644 index 0000000..0b66407 --- /dev/null +++ b/CI_CD_SETUP.md @@ -0,0 +1,109 @@ +# Branch Protection & CI/CD Setup Guide + +## What's Included + +This branch contains: +1. **GitHub Actions CI Workflow** (`.github/workflows/ci.yml`) +2. **Jest Configuration** (`jest.config.js`) +3. **Example Tests** (`src/__tests__/bot.test.js`) +4. **Updated package.json** with test scripts and dev dependencies + +## Installation Steps + +### 1. Merge This Branch +- Create a Pull Request from `add/ci-workflow` to `Main` +- Review and merge the changes + +### 2. Install Dependencies Locally +```bash +npm install +``` + +This will install: +- `jest` - Testing framework +- `supertest` - HTTP assertion library + +### 3. Run Tests Locally +```bash +# Run all tests once +npm test + +# Run tests in watch mode (re-runs on file changes) +npm run test:watch +``` + +## Branch Protection Setup + +After merging, set up branch protection rules: + +1. Go to **Settings** → **Branches** +2. Click **Add branch protection rule** +3. Enter branch name: `Main` +4. Enable these settings: + +### Required Settings +- ✅ **Require a pull request before merging** + - Require approvals: `1` + - Dismiss stale pull request approvals: ✓ + +- ✅ **Require status checks to pass before merging** + - Search for and add these status checks: + - `lint` (Code syntax checking) + - `test` (Unit tests) + - `code-quality` (Security checks) + - `build` (Build verification) + +- ✅ **Require branches to be up to date before merging** + +- ✅ **Require conversation resolution before merging** + +- ✅ **Allow force pushes** → Set to `Restrict who can force push` + - Select: `Admins only` or `No one` + +- ✅ **Allow deletions** → Set to `Restrict who can delete` + - Select: `Admins only` or `No one` + +- ✅ **Require linear history** + +- ✅ **Include administrators** (if you want protection to apply to admins too) + +## CI/CD Workflow Details + +The workflow runs automatically on: +- Push to `Main`, `main`, or `develop` +- Pull requests to those branches + +### Jobs: +1. **Lint** - Checks syntax and npm vulnerabilities +2. **Test** - Runs Jest tests with PostgreSQL +3. **Code Quality** - Detects hardcoded secrets and console statements +4. **Security** - Runs npm audit +5. **Build** - Verifies app starts correctly + +### All jobs must pass before merging! + +## Writing Your Tests + +Replace `src/__tests__/bot.test.js` with your actual tests: + +```javascript +describe('Feature Name', () => { + test('should do something', () => { + expect(result).toBe(expected); + }); +}); +``` + +## Troubleshooting + +- **Tests failing locally?** Check that Node 18+ is installed: `node --version` +- **DB connection errors?** Ensure PostgreSQL is running on port 5432 +- **Lint errors?** Follow the error messages to fix syntax issues +- **Secrets detected?** Move sensitive data to `.env` files (already in .gitignore) + +## Next Steps + +1. Merge this PR +2. Write comprehensive tests for your bot +3. Monitor CI/CD runs in the **Actions** tab +4. Keep coverage above 50% (configurable in `jest.config.js`) diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..be0d0b1 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,19 @@ +module.exports = { + testEnvironment: 'node', + collectCoverageFrom: [ + 'src/**/*.js', + '!src/**/index.js', + '!src/**/*.config.js' + ], + coverageThreshold: { + global: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }, + testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'], + verbose: true, + testTimeout: 10000 +}; diff --git a/package.json b/package.json index 9a206e7..92bbc6b 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "scripts": { "start": "node src/index.js", "dev": "nodemon src/index.js", - "init-db": "node src/database/init.js" + "init-db": "node src/database/init.js", + "test": "jest --coverage --testEnvironment=node", + "test:watch": "jest --watch" }, "keywords": [ "telegram", @@ -31,7 +33,9 @@ "stripe": "^14.10.0" }, "devDependencies": { - "nodemon": "^3.0.2" + "nodemon": "^3.0.2", + "jest": "^29.7.0", + "supertest": "^6.3.3" }, "engines": { "node": ">=18.0.0" diff --git a/src/__tests__/bot.test.js b/src/__tests__/bot.test.js new file mode 100644 index 0000000..1ea295a --- /dev/null +++ b/src/__tests__/bot.test.js @@ -0,0 +1,27 @@ +/** + * Example test file - Replace with your actual tests + * This demonstrates how to structure your test suite + */ + +describe('Bot Configuration', () => { + beforeEach(() => { + // Setup before each test + process.env.NODE_ENV = 'test'; + }); + + afterEach(() => { + // Cleanup after each test + jest.clearAllMocks(); + }); + + test('should have required environment variables configured', () => { + expect(process.env.NODE_ENV).toBe('test'); + // Add more environment variable checks as needed + }); + + test('should load dependencies correctly', () => { + const packageJson = require('../../package.json'); + expect(packageJson.name).toBe('telegram-plaid-bot'); + expect(packageJson.version).toBeDefined(); + }); +});