diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ffd6f05 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,74 @@ +version: 2 +updates: + # Backend dependencies + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + reviewers: + - "jeninh" + labels: + - "dependencies" + - "backend" + commit-message: + prefix: "chore(deps)" + groups: + minor-and-patch: + patterns: + - "*" + update-types: + - "minor" + - "patch" + + # Frontend dependencies + - package-ecosystem: "npm" + directory: "/client" + schedule: + interval: "weekly" + day: "monday" + open-pull-requests-limit: 10 + reviewers: + - "jeninh" + labels: + - "dependencies" + - "frontend" + commit-message: + prefix: "chore(deps)" + groups: + svelte-ecosystem: + patterns: + - "svelte*" + - "@sveltejs/*" + vite-ecosystem: + patterns: + - "vite*" + minor-and-patch: + patterns: + - "*" + update-types: + - "minor" + - "patch" + + # Docker base images + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "docker" + commit-message: + prefix: "chore(docker)" + + # GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + - "github-actions" + commit-message: + prefix: "chore(ci)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..52efb1e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,196 @@ +name: CI + +on: + pull_request: + branches: [main, master] + push: + branches: [main, master] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-and-format: + name: Lint & Format + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies (root) + run: npm ci + + - name: Install dependencies (client) + run: npm ci + working-directory: client + + - name: Lint backend with ESLint + run: npx eslint src/ --ext .js --max-warnings 0 + + - name: Lint client with ESLint + run: npx eslint src/ --ext .js,.svelte --max-warnings 0 + working-directory: client + + - name: Check Prettier formatting (backend) + run: npx prettier --check "src/**/*.js" + + - name: Check Prettier formatting (client) + run: npx prettier --check "src/**/*.{js,svelte}" + working-directory: client + + security: + name: Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies (root) + run: npm ci + + - name: Install dependencies (client) + run: npm ci + working-directory: client + + - name: Audit backend dependencies + run: npm audit --audit-level=high + + - name: Audit client dependencies + run: npm audit --audit-level=high + working-directory: client + + - name: Run CodeQL Analysis + uses: github/codeql-action/init@v3 + with: + languages: javascript + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies (root) + run: npm ci + + - name: Install dependencies (client) + run: npm ci + working-directory: client + + - name: Build client + run: npm run build + working-directory: client + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: client-build + path: client/dist/ + retention-days: 7 + + docker: + name: Docker Build + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: false + tags: spaces:test + cache-from: type=gha + cache-to: type=gha,mode=max + + test: + name: Test + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: spaces_test + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + DATABASE_URL: postgres://test:test@localhost:5432/spaces_test + NODE_ENV: test + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies (root) + run: npm ci + + - name: Install dependencies (client) + run: npm ci + working-directory: client + + - name: Run backend tests + run: npm test --if-present + + - name: Run client tests + run: npm test --if-present + working-directory: client + + all-checks-pass: + name: All Checks Pass + runs-on: ubuntu-latest + needs: [lint-and-format, security, build, docker, test] + if: always() + steps: + - name: Check all jobs passed + run: | + if [[ "${{ needs.lint-and-format.result }}" == "failure" ]] || \ + [[ "${{ needs.security.result }}" == "failure" ]] || \ + [[ "${{ needs.build.result }}" == "failure" ]] || \ + [[ "${{ needs.docker.result }}" == "failure" ]] || \ + [[ "${{ needs.test.result }}" == "failure" ]]; then + echo "One or more jobs failed" + exit 1 + fi + echo "All checks passed!" diff --git a/.gitignore b/.gitignore index 940bb14..ce2fd1e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ node_modules dist build AGENTS.md -.github .vscode .DS_Store .claude