Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use check release #29

Merged
merged 1 commit into from
Dec 30, 2024
Merged
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
126 changes: 78 additions & 48 deletions .github/actions/sql-review/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import { promises as fs } from 'fs';
import * as glob from 'glob';
import * as core from "@actions/core";
import * as github from "@actions/github";
import { promises as fs } from "fs";
import * as glob from "glob";

async function run(): Promise<void> {
try {
const githubToken = core.getInput('github-token', { required: true });
const pattern = core.getInput('pattern', { required: true });
const githubToken = core.getInput("github-token", { required: true });
const pattern = core.getInput("pattern", { required: true });
const octokit = github.getOctokit(githubToken);
const url = core.getInput("url", { required: true })
const token = core.getInput("token", { required: true })
const database = core.getInput("database", { required: true })
const extraHeaders: string = core.getInput('headers');
const failOnWarnings: boolean = core.getBooleanInput('fail-on-warnings');
const url = core.getInput("url", { required: true });
const token = core.getInput("token", { required: true });
const database = core.getInput("database", { required: true });
const project = core.getInput("project", { required: true });
const extraHeaders: string = core.getInput("headers");
const failOnWarnings: boolean = core.getBooleanInput("fail-on-warnings");

let headers: HeadersInit = extraHeaders ? JSON.parse(extraHeaders) : {};
headers = {
"Content-Type": "application/json",
'Authorization': `Bearer ${token}`,
...headers
Authorization: `Bearer ${token}`,
...headers,
};

const { owner, repo } = github.context.repo;
const prNumber = github.context.payload.pull_request?.number;
if (!prNumber) {
throw new Error('Could not get PR number from the context; this action should only be run on pull_request events.');
throw new Error(
"Could not get PR number from the context; this action should only be run on pull_request events."
);
}

let allChangedFiles: string[] = [];
let allChangedFiles: string[] = [];
let page = 0;
let fileList;

Expand All @@ -42,56 +45,83 @@ async function run(): Promise<void> {
page,
});

allChangedFiles.push(...fileList.data.map(file => file.filename));

allChangedFiles.push(...fileList.data.map((file) => file.filename));
} while (fileList.data.length !== 0);

// Use glob.sync to synchronously match files against the pattern
const matchedFiles = glob.sync(pattern, { nodir: true });

// Filter matchedFiles to include only those that are also in allChangedFiles
const sqlFiles = matchedFiles.filter(file => allChangedFiles.includes(file));
const sqlFiles = matchedFiles.filter((file) =>
allChangedFiles.includes(file)
);

let hasErrorOrWarning = false;
for (const file of sqlFiles) {
const content = await fs.readFile(file, 'utf8');
core.debug(`\nContent of ${file}:`);
core.debug(content);

const requestBody = {
let files = [];
for (const file of sqlFiles) {
const content = await fs.readFile(file, "utf8");
files.push({
statement: content,
name: database,
};

const response = await fetch(`${url}/v1/sql/check`, {
method: 'POST',
headers,
body: JSON.stringify(requestBody),
version: "",
changeType: "DDL",
});
}

const httpStatus = response.status;

if (httpStatus !== 200) {
throw new Error(`Failed to check SQL file ${file} with response code ${httpStatus}`);
}

const responseData = await response.json();

const response = await fetch(`${url}/v1/${project}/releases:check`, {
method: "POST",
headers,
body: JSON.stringify({
release: {
files: files,
},
targets: [database],
}),
});

const httpStatus = response.status;

if (httpStatus !== 200) {
throw new Error(
`Failed to check release with response code ${httpStatus}`
);
}

core.debug("Reviews:" + JSON.stringify(responseData.advices));
responseData.advices.forEach((advice: { status: string; line: any; column: any; title: any; code: any; content: any; }) => {
const annotation = `::${advice.status} file=${file},line=${advice.line},col=${advice.column},title=${advice.title} (${advice.code})::${advice.content}. https://www.bytebase.com/docs/reference/error-code/advisor#${advice.code}`;
// Emit annotations for each advice
core.info(annotation);

if (advice.status === 'ERROR' || (failOnWarnings && advice.status === 'WARNING')) {
hasErrorOrWarning = true;
const responseData = await response.json();

core.debug("Reviews:" + JSON.stringify(responseData.results));

for (let i = 0; i < sqlFiles.length; i++) {
const advices = responseData.results[i].advices;
const file = sqlFiles[i];

advices.forEach(
(advice: {
status: string;
line: any;
column: any;
title: any;
code: any;
content: any;
}) => {
const annotation = `::${advice.status} file=${file},line=${advice.line},col=${advice.column},title=${advice.title} (${advice.code})::${advice.content}. https://www.bytebase.com/docs/reference/error-code/advisor#${advice.code}`;
// Emit annotations for each advice
core.info(annotation);

if (
advice.status === "ERROR" ||
(failOnWarnings && advice.status === "WARNING")
) {
hasErrorOrWarning = true;
}
}
});
);
}

if (hasErrorOrWarning) {
core.setFailed("Review contains ERROR or WARNING violations. Marking for failure.");
core.setFailed(
"Review contains ERROR or WARNING violations. Marking for failure."
);
}
} catch (error) {
if (error instanceof Error) core.setFailed(error.message);
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/bytebase-sql-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jobs:
BYTEBASE_URL: "https://bytebase-ci.zeabur.app"
BYTEBASE_SERVICE_ACCOUNT: "ci@service.bytebase.com"
DATABASE: "instances/prod-instance/databases/example"
PROJECT: "projects/prj-ex"
name: SQL Review
steps:
- name: Checkout
Expand All @@ -35,3 +36,4 @@ jobs:
token: ${{ steps.login.outputs.token }}
headers: '{"Accept-Encoding": "deflate, gzip"}'
database: ${{ env.DATABASE }}
project: ${{ env.PROJECT }}
Loading