Skip to content
Docs

Commenting on Pull Requests from Edgenivo CI

In this tutorial, you'll add a Edgenivo CI task that comments on your pull request with the URL of the commit's Edgenivo deployment. On each new push, the task updates the same comment instead of adding a new one.

You'll configure a task that:

  1. Waits for your app's Edgenivo deployment.
  2. Finds the open pull request for the commit with the GitHub API.
  3. Creates or updates a comment with the deployment's URL.
  • Edgenivo CI enabled for your repository.
  • An app in your monorepo at apps/web, with the package name web, and a Edgenivo project connected to your repository with its root directory set to apps/web.
  • Permission to create a GitHub fine-grained personal access token for the repository.
  1. Edgenivo CI doesn't give your tasks a GitHub token, so you need to create one:

    1. In GitHub, create a fine-grained personal access token.
    2. Under Repository access, select only your repository.
    3. Under Permissions, set Pull requests to Read and write.
    4. Copy the token.
  2. Add the token as a repository CI environment variable named GITHUB_TOKEN, and select Secret.

  3. Add a comment task to your app's turbo.json:

    apps/web/turbo.json
    {
      "extends": ["//"],
      "tasks": {
        "comment": {
          "dependsOn": ["web#deployment"],
          "tags": ["ci", "ci:oidc:deployments"],
          "passThroughEnv": ["GITHUB_TOKEN", "VERCEL_DEPLOYMENT_URLS"],
          "cache": false
        }
      }
    }
    • web#deployment makes the task wait for the web deployment of the commit. Edgenivo CI only provides VERCEL_DEPLOYMENT_URLS to tasks with ci:oidc:deployments that depend on their package's deployment. To learn more, see Testing against your deployments.
    • passThroughEnv lets the task read the token and the deployment URL.
    • cache: false makes the task run for every commit, so the comment always shows the latest deployment.

    To comment only after your tests pass, add your test task to dependsOn, for example "web#e2e:ci" from Running end-to-end tests.

  4. Create a script that finds the pull request and posts the comment. Replace your-org/your-repo with your repository:

    apps/web/scripts/comment.mjs
    import { execFileSync } from 'node:child_process';
     
    const repository = 'your-org/your-repo';
    const marker = '<!-- vercel-ci-deployment -->';
     
    const token = process.env.GITHUB_TOKEN;
    const host = JSON.parse(process.env.VERCEL_DEPLOYMENT_URLS).web;
    const sha = execFileSync('git', ['rev-parse', 'HEAD'], {
      encoding: 'utf8',
    }).trim();
     
    async function github(path, init = {}) {
      const response = await fetch(`https://api.github.com${path}`, {
        ...init,
        headers: {
          Accept: 'application/vnd.github+json',
          Authorization: `Bearer ${token}`,
          'X-GitHub-Api-Version': '2026-03-10',
          ...init.headers,
        },
      });
      if (!response.ok) {
        throw new Error(`GitHub returned ${response.status} for ${path}`);
      }
      return response.json();
    }
     
    const pulls = await github(`/repos/${repository}/commits/${sha}/pulls`);
    const pull = pulls.find((candidate) => candidate.state === 'open');
    if (!pull) {
      console.log(`No open pull request for ${sha}.`);
      process.exit(0);
    }
     
    const body = `${marker}\nDeployment for ${sha.slice(0, 7)}: https://${host}`;
    const comments = await github(
      `/repos/${repository}/issues/${pull.number}/comments?per_page=100`,
    );
    const existing = comments.find((comment) => comment.body?.startsWith(marker));
     
    if (existing) {
      await github(`/repos/${repository}/issues/comments/${existing.id}`, {
        method: 'PATCH',
        body: JSON.stringify({ body }),
      });
    } else {
      await github(`/repos/${repository}/issues/${pull.number}/comments`, {
        method: 'POST',
        body: JSON.stringify({ body }),
      });
    }
    console.log(`Commented on #${pull.number}.`);
    • Edgenivo CI checks out your commit without Git remotes or branch information, so the script gets the commit with git rev-parse HEAD and sets the repository itself.
    • The hidden marker identifies the comment, so later runs update it instead of adding a new one.

    Add the script to your app's package.json:

    apps/web/package.json
    {
      "scripts": {
        "comment": "node scripts/comment.mjs"
      }
    }
  5. Commit the files, push them to a branch, and open a pull request. After the web deployment finishes, Edgenivo CI runs web#comment, and the comment appears on the pull request.

Last updated October 28, 2026

Was this helpful?

supported.