在 javascript github 操作中获取修改后的行号

Get modified line numbers in javascript github action

我正在尝试编写 JavaScript(在 TypeScript 中)Github 操作来检查合并请求中的代码更改。我通过这样做设法获得了修改文件的名称:

import * as github from '@actions/github';
import * as core from '@actions/core';

async function run() {
  const base = github.context.payload.pull_request.base.sha;
  const head = github.context.payload.pull_request.head.sha;

  const client = github.getOctokit(core.getInput('token', {required: true});
  const response = await client.repos.compareCommits({
    base,
    head,
    owner: context.repo.owner,
    context.repo.repo,
  });

  const files = response.data.files;
  const fileNames = files.map((file) => file.filename);
}

run ();

我也想知道修改了哪些行(只有头文件的行可以),但是好像不能从files访问,我有点卡住了。

参考,files的类型是:

{
    sha: string;
    filename: string;
    status: string;
    additions: number;
    deletions: number;
    changes: number;
    blob_url: string;
    raw_url: string;
    contents_url: string;
    patch?: string | undefined;
    previous_filename?: string | undefined;
}[]

如何获取行号?

我终于做到了。 .patch包含文件的变化,通常构造如下

"@@ -6,7 +6,9 @@ <fileCodeChanges> @@ -12,7 +12,3 <fileCodeChanges2> ..."

所有的变化都被

分隔
`@@ -${startLineDeletion},${numberOfDeletion} +${startLineAddition},${numberOfAddition} @@`

所以我只需要

  1. .patch 拆分为 "@@"
  2. 过滤代码部分以仅保留行号
  3. 提取数字

这是我的代码:

import * as github from '@actions/github';
import * as core from '@actions/core';

interface FileLines {
  start: number;
  end: number
}

export interface ModifiedFile {
  name: string;
  deletion?: FileLines[];
  addition?: FileLines[];
}


async function run() {
  const base = github.context.payload.pull_request.base.sha;
  const head = github.context.payload.pull_request.head.sha;

  const client = github.getOctokit(core.getInput('token', {required: true});
  const response = await client.repos.compareCommits({
    base,
    head,
    owner: context.repo.owner,
    context.repo.repo,
  });

  const files = response.data.files;
  const modifiedFilesWithModifiedLines = files.map(parseFile);
}

function parseFile(file: {filename: string, patch?: string|undefined}): ModifiedFile {
  const modifiedFile: ModifiedFile = {
    name: file.filename
  };
  if (file.patch) {
    // The changes are included in the file
    const patches = file.patch.split('@@').filter((_, index) => index % 2); // Only take the line information and discard the modified code
    for (const patch of patches) {
      // patch is usually like " -6,7 +6,8"
      try {
        const hasAddition = patch.includes('+');
        const hasDeletion = patch.includes('-');
        if (hasAddition) {
          const lines = patch.match(/\+.*/)![0].trim().slice(1).split(',').map(num) => parseInt(num)) as [number, number];
          modifiedFile.addition ??= [];
          modifiedFile.addition?.push({
            start: lines[0],
            end: lines[0] + lines[1],
          });
        }
        if (hasDeletion) {

          const lines = patch.split('+')[0].trim().slice(1).split(',').map((num) => parseInt(num)) as [number, number];
          modifiedFile.deletion ??= [];
          modifiedFile.deletion?.push({
            start: lines[0],
            end: lines[0] + lines[1],
          });
        }

      } catch (error) {
        console.log(`Error getting the patch of the file:\n${error}`);
      }
    }
  } else {
    // Take the all file
    modifiedFile.addition = [{
        start: 0,
        end: Infinity,
    }];
    modifiedFile.deletion = [{
        start: 0,
        end: Infinity,
    }];
  }
  return modifiedFile;

run ();