Skip to content
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
16 changes: 10 additions & 6 deletions .buildkite/scripts/common/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,23 @@ check_for_changed_files() {
echo "'$1' caused changes to the following files:"
echo "$GIT_CHANGES"
echo ""
echo "Auto-committing & pushing these changes now."

git config --global user.name kibanamachine
git config --global user.email '[email protected]'
gh pr checkout "${BUILDKITE_PULL_REQUEST}"
git add -A -- . ':!config/node.options' ':!config/kibana.yml'

git commit -m "$CUSTOM_FIX_MESSAGE"
git push

# Wait to ensure all commits arrive before we terminate the build
sleep 300
# Still exit with error to fail the current build, a new build should be started after the push
# If COLLECT_COMMITS_MARKER_FILE is set, we're in batch mode (e.g., called from quick checks runner)
# Just record the commit for later batch push
# Otherwise, commit and push immediately (standalone usage)
if [[ -n "${COLLECT_COMMITS_MARKER_FILE:-}" ]]; then
echo "Auto-committing these changes (will push after all checks complete)."
echo "$CUSTOM_FIX_MESSAGE" >> "$COLLECT_COMMITS_MARKER_FILE"
else
echo "Auto-committing and pushing these changes."
git push
fi
exit 1
else
echo -e "\n${RED}ERROR: '$1' caused changes to the following files:${C_RESET}\n"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,6 @@ x-pack/solutions/security/test/security_solution_playwright/.env
.dependency-graph-log.json

.moon/cache

# Batched commits marker, e.g.: from quick checks
.collect_commits_marker
2 changes: 1 addition & 1 deletion src/core/test-helpers/kbn-server/moon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ dependsOn:
- '@kbn/config'
- '@kbn/core-lifecycle-server-internal'
- '@kbn/core-root-server-internal'
- '@kbn/repo-info'
- '@kbn/repo-packages'
- '@kbn/es'
- '@kbn/dev-utils'
- '@kbn/safer-lodash-set'
- '@kbn/repo-info'
tags:
- shared-server
- package
Expand Down
2 changes: 1 addition & 1 deletion src/core/test-helpers/kbn-server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
"@kbn/config",
"@kbn/core-lifecycle-server-internal",
"@kbn/core-root-server-internal",
"@kbn/repo-info",
"@kbn/repo-packages",
"@kbn/es",
"@kbn/dev-utils",
"@kbn/safer-lodash-set",
"@kbn/repo-info",
],
"exclude": [
"target/**/*",
Expand Down
69 changes: 66 additions & 3 deletions src/dev/run_quick_checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { execFile } from 'child_process';
import { availableParallelism } from 'os';
import { isAbsolute, join } from 'path';
import { existsSync, readdirSync, readFileSync } from 'fs';
import { existsSync, readdirSync, readFileSync, unlinkSync } from 'fs';

import { run, RunOptions } from '@kbn/dev-cli-runner';
import { REPO_ROOT } from '@kbn/repo-info';
Expand All @@ -20,6 +20,7 @@ const MAX_PARALLELISM = availableParallelism();
const buildkiteQuickchecksFolder = join('.buildkite', 'scripts', 'steps', 'checks');
const quickChecksList = join(buildkiteQuickchecksFolder, 'quick_checks.json');
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const COLLECT_COMMITS_MARKER_FILE = join(REPO_ROOT, '.collect_commits_marker');

interface QuickCheck {
script: string;
Expand Down Expand Up @@ -57,6 +58,14 @@ let logger: ToolingLog;
void run(async ({ log, flagsReader }) => {
logger = log;

// Clean up any existing marker file from previous runs
if (existsSync(COLLECT_COMMITS_MARKER_FILE)) {
unlinkSync(COLLECT_COMMITS_MARKER_FILE);
}

// Set environment variable so check scripts know where to write the marker file
process.env.COLLECT_COMMITS_MARKER_FILE = COLLECT_COMMITS_MARKER_FILE;

const checksToRun = collectScriptsToRun({
targetFile: flagsReader.string('file'),
targetDir: flagsReader.string('dir'),
Expand All @@ -81,12 +90,36 @@ void run(async ({ log, flagsReader }) => {
logger.write('--- All checks finished.');
printResults(startTime, results);

// Check if any commits were made and push them in a single batch
// This allows multiple quick-check fixes to be committed and pushed together,
// avoiding multiple CI restarts when a PR has multiple offenses.
// File-changing checks run with parallelism=1 (sequentially), so commits happen
// one at a time without conflicts.
const commitsWereMade = existsSync(COLLECT_COMMITS_MARKER_FILE);
if (commitsWereMade) {
logger.write('--- Commits were made during checks. Pushing all changes now...');
try {
await pushCommits();
logger.write('--- Successfully pushed all commits.');
// Clean up marker file
if (existsSync(COLLECT_COMMITS_MARKER_FILE)) {
unlinkSync(COLLECT_COMMITS_MARKER_FILE);
}
// Still exit with error to fail the current build, a new build should be started after the push
logger.write('--- Build will fail to trigger a new build with the fixes.');
process.exitCode = 1;
} catch (error) {
logger.error(`--- Failed to push commits: ${error}`);
process.exitCode = 1;
}
}

const failedChecks = results.filter((check) => !check.success);
if (failedChecks.length > 0) {
logger.write(`--- ${failedChecks.length} quick check(s) failed. ❌`);
logger.write(`See the script(s) marked with ❌ above for details.`);
process.exitCode = 1;
} else {
} else if (!commitsWereMade) {
logger.write('--- All checks passed. ✅');
return results;
}
Expand Down Expand Up @@ -188,7 +221,10 @@ async function runCheckAsync(script: string): Promise<CheckResult> {

return new Promise((resolve) => {
validateScriptPath(script);
const scriptProcess = execFile('bash', [script]);
// Pass environment variables to child process, including COLLECT_COMMITS_MARKER_FILE
const scriptProcess = execFile('bash', [script], {
env: { ...process.env },
});
let output = '';
const appendToOutput = (data: string | Buffer) => (output += data.toString());

Expand Down Expand Up @@ -264,3 +300,30 @@ function validateScriptPath(scriptPath: string) {
function stripRoot(script: string) {
return script.replace(REPO_ROOT, '');
}

async function pushCommits(): Promise<void> {
return new Promise((resolve, reject) => {
const pushProcess = execFile('git', ['push'], {
cwd: REPO_ROOT,
env: { ...process.env },
});

let output = '';
const appendToOutput = (data: string | Buffer) => (output += data.toString());

pushProcess.stdout?.on('data', appendToOutput);
pushProcess.stderr?.on('data', appendToOutput);

pushProcess.on('exit', (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error(`git push failed with code ${code}: ${output}`));
}
});

pushProcess.on('error', (error) => {
reject(error);
});
});
}