Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ dist/
.github/
Dockerfile
*.md
azure-deploy/
infra/
playwright-report/
test-results/
test-results-docker/
test-results-docker-ent/
test-results-docker-org/
File renamed without changes.
96 changes: 96 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 10
permissions:
checks: write
pull-requests: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: CI=true npm test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30

test-api-org:
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and export to Docker
uses: docker/build-push-action@v6
with:
file: api.Dockerfile
load: true
tags: api:test
build-args: mode=playwright
- name: Run Playwright tests
run: |
docker run --rm --name playwright \
-v $(pwd)/test-results-docker-org:/test-results \
-e CI=true \
-e VUE_APP_SCOPE=organization \
-e VUE_APP_GITHUB_ORG=octodemo \
-e VUE_APP_GITHUB_API=/api/github \
-e APP_MOCKED_DATA=true \
-e VUE_APP_GITHUB_TOKEN=dummy \
-e SESSION_SECRET=dummy \
api:test "@org"
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report-docker-org
path: test-results-docker-org/
retention-days: 30

test-api-ent:
timeout-minutes: 15
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and export to Docker
uses: docker/build-push-action@v6
with:
file: api.Dockerfile
load: true
tags: api:test
build-args: mode=playwright
- name: Run Playwright tests
run: |
docker run --rm --name playwright \
-v $(pwd)/test-results-docker-ent:/test-results \
-e CI=true \
-e VUE_APP_SCOPE=enterprise \
-e VUE_APP_GITHUB_ENT=octodemo \
-e VUE_APP_GITHUB_API=/api/github \
-e APP_MOCKED_DATA=true \
-e VUE_APP_GITHUB_TOKEN=dummy \
-e SESSION_SECRET=dummy \
api:test "@ent"
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report-docker-ent
path: test-results-docker-ent/
retention-days: 30
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ pnpm-debug.log*

api/public
test.http
/test-results/
/test-results-docker/
/playwright-report/
/blob-report/
/playwright/.cache/
test-results-docker-ent/
test-results-docker-org/
41 changes: 37 additions & 4 deletions api.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
# Stage 1: Build the Vue.js application
# mode can be 'prod' - default or 'playwright'
# for 'playwright' mode, the final image will be base-playwright
# for 'prod' mode, the final image will be base-prod
# build with 'docker build -f api.Dockerfile -t api --build-arg mode=playwright .'
# build with 'docker build -f api.Dockerfile -t api .' for production
ARG mode=prod

FROM node:23 AS build-stage

USER node
WORKDIR /app

COPY --chown=1000:1000 package*.json ./
RUN npm install
RUN npm ci
COPY --chown=1000:1000 . .
RUN npm run build

# Stage 2: Prepare the Node.js API
FROM node:23 AS api-stage
FROM node:23 AS base-prod

WORKDIR /api

# Copy package.json and other necessary files for the API
COPY --chown=1000:1000 api/package*.json ./
RUN npm install && \
RUN npm ci && \
chown -R 1000:1000 /api && \
apt-get update && \
apt-get install -y --no-install-recommends gettext-base && \
Expand All @@ -29,6 +36,7 @@ COPY --chown=1000:1000 api/ .
# Copy the built Vue.js app from the previous stage
COPY --chown=1000:1000 --from=build-stage /app/dist /api/public
COPY --chown=1000:1000 --from=build-stage /app/dist/assets/app-config.js /api/app-config.template.js
COPY --chown=1000:1000 --from=build-stage /app/mock-data /mock-data

# Expose the port your API will run on
EXPOSE 3000
Expand All @@ -37,4 +45,29 @@ EXPOSE 3000
RUN chmod +x /api/docker-entrypoint.api/entrypoint.sh

USER node
ENTRYPOINT ["/api/docker-entrypoint.api/entrypoint.sh"]
ENTRYPOINT ["/api/docker-entrypoint.api/entrypoint.sh"]

#-----------------------------------
FROM mcr.microsoft.com/playwright:v1.49.1 AS base-playwright

WORKDIR /pw

RUN apt-get update && \
apt-get install -y --no-install-recommends gettext-base && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

COPY --chown=1000:1000 --from=base-prod /api /api
COPY --chown=1000:1000 --from=base-prod /mock-data /mock-data
COPY --chown=1000:1000 tests ./tests
COPY --chown=1000:1000 playwright.config.ts .
COPY --chown=1000:1000 playwright.docker.config.ts .


RUN npm install @playwright/[email protected]
# RUN npx playwright install --with-deps

ENTRYPOINT [ "npx", "playwright", "test", "-c", "playwright.docker.config.ts", "--output", "/test-results", "--grep"]

#-----------------------------------
FROM base-${mode} AS final
40 changes: 36 additions & 4 deletions api/server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import axios from 'axios';
import { fileURLToPath } from 'url';
import session from 'express-session';
import { createProxyMiddleware } from 'http-proxy-middleware';
import { readFileSync } from 'fs';

// Construct __dirname equivalent in ES module scope
const __dirname = path.dirname(fileURLToPath(import.meta.url));
Expand Down Expand Up @@ -45,16 +46,47 @@ const authMiddleware = (req, res, next) => {
next();
};

const simpleRequestLogger = (proxyServer, options) => {
proxyServer.on('proxyReq', (proxyReq, req, res) => {
console.log(`[HPM] [${req.method}] ${req.url}`); // outputs: [HPM] GET /users
});
}

const mockResponses = (proxyServer, options) => {
proxyServer.on('proxyReq', (proxyReq, req, res) => {
// Do not send to GitHub when mocked
switch (req.path) {
case "/orgs/octodemo/copilot/usage":
res.json(JSON.parse(readFileSync(path.join(__dirname, '../mock-data/organization_response_sample.json'), 'utf8')));
break;
case "/orgs/octodemo/copilot/billing/seats":
res.json(JSON.parse(readFileSync(path.join(__dirname, '../mock-data/organization_response_sample_seats.json'), 'utf8')));
break;
case "/enterprises/octodemo/copilot/usage":
res.json(JSON.parse(readFileSync(path.join(__dirname, '../mock-data/enterprise_response_sample.json'), 'utf8')));
break;
case "/enterprises/octodemo/copilot/billing/seats":
res.json(JSON.parse(readFileSync(path.join(__dirname, '../mock-data/enterprise_response_sample_seats.json'), 'utf8')));
break;
default:
res.status(418).send('🫖Request Not Mocked');
}
});
}

const plugins = [simpleRequestLogger];

if (process.env.APP_MOCKED_DATA === 'true') {
plugins.push(mockResponses);
}

const githubProxy = createProxyMiddleware({
target: 'https://api.github.com',
changeOrigin: true,
pathRewrite: {
'^/api/github': '', // Rewrite URL path (remove /api/github)
},
onProxyReq: (proxyReq, req) => {
console.log('Proxying request to GitHub API:', req.url);
// Optional: Modify the proxy request here (e.g., headers)
},
plugins
});

// Apply middlewares to the app
Expand Down
Loading
Loading