diff --git a/.github/workflows/deploy_proxy_to_ghcr.yml b/.github/workflows/deploy_proxy_to_ghcr.yml deleted file mode 100644 index 9e4698c..0000000 --- a/.github/workflows/deploy_proxy_to_ghcr.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Build and push Docker image for Proxy - -on: - push: - branches: - - main - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -permissions: - packages: write - -jobs: - push_to_ghcr: - runs-on: ubuntu-latest - steps: - - name: Checkout GitHub Action - uses: actions/checkout@v4 - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and Push Docker Image - run: | - GITHUB_REPO="${GITHUB_REPO,,}-with-proxy" # convert repo name to lowercase as required by docker - echo "building docker image in repository '$GITHUB_REPO' ..." - docker build -f api.Dockerfile --label "org.opencontainers.image.title=copilot-metrics-viewer-with-proxy" --label "org.opencontainers.image.description=Metrics viewer with proxy for GitHub Copilot usage" --label "org.opencontainers.image.source=$GITHUB_REPO" -t ghcr.io/$GITHUB_REPO:latest . - docker push ghcr.io/$GITHUB_REPO:latest - env: - GITHUB_REPO: ${{ github.repository }} \ No newline at end of file diff --git a/.github/workflows/deploy_to_ghcr.yml b/.github/workflows/deploy_to_ghcr.yml index 852dbc5..539284d 100644 --- a/.github/workflows/deploy_to_ghcr.yml +++ b/.github/workflows/deploy_to_ghcr.yml @@ -25,14 +25,73 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and Push Docker Image - run: | - GITHUB_REPO="${GITHUB_REPO,,}" # convert repo name to lowercase as required by docker - echo "building docker image in repository '$GITHUB_REPO' ..." - docker build --label "org.opencontainers.image.title=copilot-metrics-viewer" --label "org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage" --label "org.opencontainers.image.source=$GITHUB_REPO" -t ghcr.io/$GITHUB_REPO:latest . - docker push ghcr.io/$GITHUB_REPO:latest - env: - GITHUB_REPO: ${{ github.repository }} + # Adding below tag any push to main as "latest" + # To deploy latest, create a release with a semver tag + # type=raw,value=latest,enable={{is_default_branch}} + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + labels: | + org.opencontainers.image.title=copilot-metrics-viewer + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true + + push_proxy_to_ghcr: + runs-on: ubuntu-latest + steps: + - name: Checkout GitHub Action + uses: actions/checkout@v4 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Adding below tag any push to main as "latest" + # To deploy latest, create a release with a semver tag + # type=raw,value=latest,enable={{is_default_branch}} + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}-with-proxy + labels: | + org.opencontainers.image.title=copilot-metrics-viewer-with-proxy + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push api + uses: docker/build-push-action@v5 + with: + context: . + file: api.Dockerfile + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true deploy: runs-on: ubuntu-latest @@ -49,4 +108,4 @@ jobs: app-name: 'copilot-metrics-viewer' slot-name: 'production' publish-profile: ${{ secrets.AzureAppService_PublishProfile_e94dfd38811a421eafe5ce4eee13b68b }} - images: 'ghcr.io/github-copilot-resources/copilot-metrics-viewer:latest' + images: 'ghcr.io/github-copilot-resources/copilot-metrics-viewer:main' diff --git a/.github/workflows/deploy_to_ghcr_custom_tag.yaml b/.github/workflows/deploy_to_ghcr_custom_tag.yaml index a02a12a..c53f613 100644 --- a/.github/workflows/deploy_to_ghcr_custom_tag.yaml +++ b/.github/workflows/deploy_to_ghcr_custom_tag.yaml @@ -1,12 +1,13 @@ name: Build and push Docker image with custom tag +# NOTE: this pipeline is not needed as images are pushed after release on: workflow_dispatch: inputs: tag: - description: 'Tag for the Docker image' + description: 'existing git tag to be used as tag for the Docker image e.g. "custom-tag"' required: true - default: 'latest' + default: 'my-tag' permissions: packages: write @@ -19,9 +20,49 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch all history for all tags and branches + ref: ${{ github.event.inputs.tag }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }} + labels: | + org.opencontainers.image.title=copilot-metrics-viewer + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=raw,enable=true,priority=1,value=${{ github.event.inputs.tag }} + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true + + push_proxy_to_ghcr: + runs-on: ubuntu-latest + steps: + - name: Checkout GitHub Action + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + ref: ${{ github.event.inputs.tag }} - - name: Checkout specific tag - run: git checkout tags/v${{ github.event.inputs.tag }} - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -30,12 +71,29 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and Push Docker Image - run: | - GITHUB_REPO="${GITHUB_REPO,,}" # convert repo name to lowercase as required by docker - TAG=${{ github.event.inputs.tag }} - echo "building docker image in repository '$GITHUB_REPO' with tag '$TAG' ..." - docker build --label "org.opencontainers.image.title=copilot-metrics-viewer" --label "org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage" --label "org.opencontainers.image.source=$GITHUB_REPO" -t ghcr.io/$GITHUB_REPO:$TAG . - docker push ghcr.io/$GITHUB_REPO:$TAG - env: - GITHUB_REPO: ${{ github.repository }} + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}-with-proxy + labels: | + org.opencontainers.image.title=copilot-metrics-viewer-with-proxy + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=raw,enable=true,priority=1,value=${{ github.event.inputs.tag }} + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push api + uses: docker/build-push-action@v5 + with: + context: . + file: api.Dockerfile + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true + \ No newline at end of file diff --git a/.github/workflows/deploy_to_ghcr_tag_release.yaml b/.github/workflows/deploy_to_ghcr_tag_release.yaml index 869c6fe..b6254a6 100644 --- a/.github/workflows/deploy_to_ghcr_tag_release.yaml +++ b/.github/workflows/deploy_to_ghcr_tag_release.yaml @@ -11,24 +11,77 @@ on: permissions: packages: write + contents: write jobs: + version_update: + runs-on: ubuntu-latest + steps: + - name: Checkout GitHub Action + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions4git/setup-git@v1 + + - name: Update version in package.json + id: version + run: | + git checkout -b temp-version-update + version=$(npm version from-git --no-git-tag-version) + cd api + npm version from-git --no-git-tag-version + git add package.json + git commit --signoff --message $version + git checkout main + git merge temp-version-update + git tag --force $version + git push origin main -f --tags + push_to_ghcr: runs-on: ubuntu-latest + needs: version_update steps: - name: Checkout GitHub Action uses: actions/checkout@v4 - - name: Get Latest Release Tag - id: get_latest_release - uses: actions/github-script@v6 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 with: - script: | - const latestRelease = await github.rest.repos.getLatestRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - }); - core.setOutput('tag_name', latestRelease.data.tag_name); + images: ghcr.io/${{ github.repository }} + labels: | + org.opencontainers.image.title=copilot-metrics-viewer + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true + + push_proxy_to_ghcr: + runs-on: ubuntu-latest + needs: version_update + steps: + - name: Checkout GitHub Action + uses: actions/checkout@v4 - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -36,13 +89,29 @@ jobs: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ghcr.io/${{ github.repository }}-with-proxy + labels: | + org.opencontainers.image.title=copilot-metrics-viewer-with-proxy + org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage + org.opencontainers.image.source=${{ github.repository }} + tags: | + type=sha + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} - - name: Build and Push Docker Image - run: | - GITHUB_REPO="${GITHUB_REPO,,}" # convert repo name to lowercase as required by docker - TAG=${{ steps.get_latest_release.outputs.result }} - echo "building docker image in repository '$GITHUB_REPO' with tag '$TAG' ..." - docker build --label "org.opencontainers.image.title=copilot-metrics-viewer" --label "org.opencontainers.image.description=Metrics viewer for GitHub Copilot usage" --label "org.opencontainers.image.source=$GITHUB_REPO" -t ghcr.io/$GITHUB_REPO:$TAG . - docker push ghcr.io/$GITHUB_REPO:$TAG - env: - GITHUB_REPO: ${{ github.repository }} + - name: Build and push api + uses: docker/build-push-action@v5 + with: + context: . + file: api.Dockerfile + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + push: true + \ No newline at end of file diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index df1c574..47cae9f 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -5,6 +5,20 @@ on: pull_request: branches: [ main, master ] jobs: + test-docker: + 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: Dockerfile + load: true + tags: ui:test + test: timeout-minutes: 10 permissions: diff --git a/api/server.mjs b/api/server.mjs index e51b205..c433fe6 100644 --- a/api/server.mjs +++ b/api/server.mjs @@ -16,7 +16,7 @@ const DOTENV_CONFIG_PATH = process.env.DOTENV_CONFIG_PATH; const MemoryStore = MemoryStoreFactory(session); const limiter = RateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes - max: 100, // max 100 requests per windowMs + max: 1000, // max 1000 requests per windowMs skip: (req) => { // Skip rate limiting for localhost return isLocalhost(req); @@ -160,6 +160,12 @@ app.get('/login', (req, res) => { res.redirect(`https://github.com/login/oauth/authorize?client_id=${process.env.GITHUB_CLIENT_ID}&redirect_uri=${redirectUrl}&state=${req.session.state}`); }); +app.get('/logout', (req, res) => { + // destroy the session + req.session.destroy(); + res.redirect('/'); +}); + app.get('/callback', async (req, res) => { const code = req.query.code; const state = req.query.state; diff --git a/src/App.vue b/src/App.vue index f04991f..ad8f5f6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,13 @@ @@ -17,9 +22,9 @@ export default defineComponent({ MainComponent, }, - data () { + data() { return { - // + version: process.env.VUE_APP_VERSION || '0.0.0' } }, }) diff --git a/src/components/MetricsViewer.vue b/src/components/MetricsViewer.vue index e19b5e7..b0d6e5d 100644 --- a/src/components/MetricsViewer.vue +++ b/src/components/MetricsViewer.vue @@ -20,7 +20,7 @@
-
Total count of Suggestions(Prompts)
+
Total count of Suggestions (Prompts)
Over the last 28 days
diff --git a/tests/metrics.spec.ts b/tests/metrics.spec.ts index 2cd587d..53a1e3d 100644 --- a/tests/metrics.spec.ts +++ b/tests/metrics.spec.ts @@ -6,7 +6,7 @@ test('metrics visible', tag, async ({ page }) => { await page.goto('/'); await expect(page.getByText('Acceptance Rate (by count)')).toBeVisible(); - await expect(page.getByText('Total count of Suggestions(Prompts)')).toBeVisible(); + await expect(page.getByText('Total count of Suggestions (Prompts)')).toBeVisible(); await expect(page.getByRole('heading', { name: 'Total Lines Suggested | Total' })).toBeVisible(); }); @@ -20,7 +20,7 @@ test('data returned', tag, async ({ page }) => { expect(parseInt(linesAccepted as string)).toBeGreaterThan(0); await expect(page.getByText('Acceptance Rate (by count)')).toBeVisible(); - await expect(page.getByText('Total count of Suggestions(Prompts)')).toBeVisible(); + await expect(page.getByText('Total count of Suggestions (Prompts)')).toBeVisible(); await expect(page.getByRole('heading', { name: 'Total Lines Suggested | Total' })).toBeVisible(); }); diff --git a/vue.config.js b/vue.config.js index cff0e67..a4ead68 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,4 +1,8 @@ const { defineConfig } = require('@vue/cli-service') +const version = require('./package.json').version; + +process.env.VUE_APP_VERSION = version; + module.exports = defineConfig({ transpileDependencies: true,