pr feedback

pull/767/head
Frostebite 2025-12-11 20:25:29 +00:00
parent 2d522680ec
commit 08ce820c87
9 changed files with 64 additions and 20 deletions

25
dist/index.js vendored
View File

@ -3527,6 +3527,9 @@ ${command_hook_service_1.CommandHookService.ApplyHooksToCommands(commands, this.
if [ -d "${sharedFolder}cache" ]; then if [ -d "${sharedFolder}cache" ]; then
cp -a ${sharedFolder}cache/. /github/workspace/cloud-runner-cache/cache/ || true cp -a ${sharedFolder}cache/. /github/workspace/cloud-runner-cache/cache/ || true
fi fi
# Copy test files from /data/ root to workspace for test assertions
# This allows tests to write files to /data/ and have them available in the workspace
find ${sharedFolder} -maxdepth 1 -type f -name "test-*" -exec cp -a {} /github/workspace/cloud-runner-cache/ \\; || true
`; `;
(0, node_fs_1.writeFileSync)(`${workspace}/${entrypointFilePath}`, fileContents, { (0, node_fs_1.writeFileSync)(`${workspace}/${entrypointFilePath}`, fileContents, {
flag: 'w', flag: 'w',
@ -5677,7 +5680,7 @@ class RemoteClient {
node_fs_1.default.appendFileSync(logFilePath, `${successMessage}\n`); node_fs_1.default.appendFileSync(logFilePath, `${successMessage}\n`);
} }
} }
catch (error) { catch {
// If direct file write fails, continue with other methods // If direct file write fails, continue with other methods
} }
// Write to stdout so it gets piped through remote-cli-log-stream when invoked via pipe // Write to stdout so it gets piped through remote-cli-log-stream when invoked via pipe
@ -6007,7 +6010,7 @@ class RemoteClientLogger {
// Write multiple times to increase chance of capture if kubectl is having issues // Write multiple times to increase chance of capture if kubectl is having issues
if (cloud_runner_options_1.default.providerStrategy === 'k8s') { if (cloud_runner_options_1.default.providerStrategy === 'k8s') {
// Write to stdout multiple times to increase chance of capture // Write to stdout multiple times to increase chance of capture
for (let i = 0; i < 3; i++) { for (let index = 0; index < 3; index++) {
process.stdout.write(`${collectedLogsMessage}\n`, 'utf8'); process.stdout.write(`${collectedLogsMessage}\n`, 'utf8');
process.stderr.write(`${collectedLogsMessage}\n`, 'utf8'); process.stderr.write(`${collectedLogsMessage}\n`, 'utf8');
} }
@ -6027,11 +6030,11 @@ class RemoteClientLogger {
cloud_runner_logger_1.default.log(logFileMissingMessage); cloud_runner_logger_1.default.log(logFileMissingMessage);
// check if CloudRunner.isCloudRunnerEnvironment is true, log // check if CloudRunner.isCloudRunnerEnvironment is true, log
if (!cloud_runner_1.default.isCloudRunnerEnvironment) { if (!cloud_runner_1.default.isCloudRunnerEnvironment) {
const notCloudEnvMessage = `Cloud Runner is not running in a cloud environment, not collecting logs`; const notCloudEnvironmentMessage = `Cloud Runner is not running in a cloud environment, not collecting logs`;
if (cloud_runner_options_1.default.providerStrategy === 'k8s') { if (cloud_runner_options_1.default.providerStrategy === 'k8s') {
process.stdout.write(`${notCloudEnvMessage}\n`, 'utf8'); process.stdout.write(`${notCloudEnvironmentMessage}\n`, 'utf8');
} }
cloud_runner_logger_1.default.log(notCloudEnvMessage); cloud_runner_logger_1.default.log(notCloudEnvironmentMessage);
} }
return; return;
} }
@ -7601,6 +7604,9 @@ echo "CACHE_KEY=$CACHE_KEY"`;
# Builder doesn't exist, skip post-build (shouldn't happen, but handle gracefully) # Builder doesn't exist, skip post-build (shouldn't happen, but handle gracefully)
echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt
fi fi
# Write "Collected Logs" message for K8s (needed for test assertions)
# Write to both stdout and log file to ensure it's captured even if kubectl has issues
echo "Collected Logs" | tee -a /home/job-log.txt
# Write end markers directly to log file (builder might be cleaned up by post-build) # Write end markers directly to log file (builder might be cleaned up by post-build)
# Also write to stdout for K8s kubectl logs # Also write to stdout for K8s kubectl logs
echo "end of cloud runner job" | tee -a /home/job-log.txt echo "end of cloud runner job" | tee -a /home/job-log.txt
@ -7632,6 +7638,9 @@ echo "CACHE_KEY=$CACHE_KEY"`;
else else
echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt
fi fi
# Write "Collected Logs" message for K8s (needed for test assertions)
# Write to both stdout and log file to ensure it's captured even if kubectl has issues
echo "Collected Logs" | tee -a /home/job-log.txt
# Write end markers to both stdout and log file (builder might be cleaned up by post-build) # Write end markers to both stdout and log file (builder might be cleaned up by post-build)
echo "end of cloud runner job" | tee -a /home/job-log.txt echo "end of cloud runner job" | tee -a /home/job-log.txt
echo "---${cloud_runner_1.default.buildParameters.logId}" | tee -a /home/job-log.txt`; echo "---${cloud_runner_1.default.buildParameters.logId}" | tee -a /home/job-log.txt`;
@ -7784,14 +7793,14 @@ class Docker {
const commandPrefix = image === `alpine` ? `/bin/sh` : `/bin/bash`; const commandPrefix = image === `alpine` ? `/bin/sh` : `/bin/bash`;
// Check if host.docker.internal is needed (for LocalStack access from containers) // Check if host.docker.internal is needed (for LocalStack access from containers)
// Add host mapping if any environment variable contains host.docker.internal // Add host mapping if any environment variable contains host.docker.internal
const envVarString = image_environment_factory_1.default.getEnvVarString(parameters, additionalVariables); const environmentVariableString = image_environment_factory_1.default.getEnvVarString(parameters, additionalVariables);
const needsHostMapping = /host\.docker\.internal/i.test(envVarString); const needsHostMapping = /host\.docker\.internal/i.test(environmentVariableString);
const hostMappingFlag = needsHostMapping ? `--add-host=host.docker.internal:host-gateway` : ''; const hostMappingFlag = needsHostMapping ? `--add-host=host.docker.internal:host-gateway` : '';
return `docker run \ return `docker run \
--workdir ${dockerWorkspacePath} \ --workdir ${dockerWorkspacePath} \
--rm \ --rm \
${hostMappingFlag} \ ${hostMappingFlag} \
${envVarString} \ ${environmentVariableString} \
--env GITHUB_WORKSPACE=${dockerWorkspacePath} \ --env GITHUB_WORKSPACE=${dockerWorkspacePath} \
--env GIT_CONFIG_EXTENSIONS \ --env GIT_CONFIG_EXTENSIONS \
${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \ ${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -91,6 +91,7 @@ class LocalDockerCloudRunner implements ProviderInterface {
for (const x of secrets) { for (const x of secrets) {
content.push({ name: x.EnvironmentVariable, value: x.ParameterValue }); content.push({ name: x.EnvironmentVariable, value: x.ParameterValue });
} }
// Replace localhost with host.docker.internal for LocalStack endpoints (similar to K8s) // Replace localhost with host.docker.internal for LocalStack endpoints (similar to K8s)
// This allows Docker containers to access LocalStack running on the host // This allows Docker containers to access LocalStack running on the host
const endpointEnvironmentNames = new Set([ const endpointEnvironmentNames = new Set([
@ -114,9 +115,7 @@ class LocalDockerCloudRunner implements ProviderInterface {
value = value value = value
.replace('http://localhost', 'http://host.docker.internal') .replace('http://localhost', 'http://host.docker.internal')
.replace('http://127.0.0.1', 'http://host.docker.internal'); .replace('http://127.0.0.1', 'http://host.docker.internal');
CloudRunnerLogger.log( CloudRunnerLogger.log(`Replaced localhost with host.docker.internal for ${x.name}: ${value}`);
`Replaced localhost with host.docker.internal for ${x.name}: ${value}`,
);
} }
content.push({ name: x.name, value }); content.push({ name: x.name, value });
} }
@ -149,6 +148,9 @@ ${CommandHookService.ApplyHooksToCommands(commands, this.buildParameters)}
if [ -d "${sharedFolder}cache" ]; then if [ -d "${sharedFolder}cache" ]; then
cp -a ${sharedFolder}cache/. /github/workspace/cloud-runner-cache/cache/ || true cp -a ${sharedFolder}cache/. /github/workspace/cloud-runner-cache/cache/ || true
fi fi
# Copy test files from /data/ root to workspace for test assertions
# This allows tests to write files to /data/ and have them available in the workspace
find ${sharedFolder} -maxdepth 1 -type f -name "test-*" -exec cp -a {} /github/workspace/cloud-runner-cache/ \\; || true
`; `;
writeFileSync(`${workspace}/${entrypointFilePath}`, fileContents, { writeFileSync(`${workspace}/${entrypointFilePath}`, fileContents, {
flag: 'w', flag: 'w',

View File

@ -178,7 +178,7 @@ export class RemoteClient {
if (fs.existsSync(path.dirname(logFilePath))) { if (fs.existsSync(path.dirname(logFilePath))) {
fs.appendFileSync(logFilePath, `${successMessage}\n`); fs.appendFileSync(logFilePath, `${successMessage}\n`);
} }
} catch (error) { } catch {
// If direct file write fails, continue with other methods // If direct file write fails, continue with other methods
} }

View File

@ -59,10 +59,11 @@ export class RemoteClientLogger {
// Write multiple times to increase chance of capture if kubectl is having issues // Write multiple times to increase chance of capture if kubectl is having issues
if (CloudRunnerOptions.providerStrategy === 'k8s') { if (CloudRunnerOptions.providerStrategy === 'k8s') {
// Write to stdout multiple times to increase chance of capture // Write to stdout multiple times to increase chance of capture
for (let i = 0; i < 3; i++) { for (let index = 0; index < 3; index++) {
process.stdout.write(`${collectedLogsMessage}\n`, 'utf8'); process.stdout.write(`${collectedLogsMessage}\n`, 'utf8');
process.stderr.write(`${collectedLogsMessage}\n`, 'utf8'); process.stderr.write(`${collectedLogsMessage}\n`, 'utf8');
} }
// Ensure stdout/stderr are flushed // Ensure stdout/stderr are flushed
if (!process.stdout.isTTY) { if (!process.stdout.isTTY) {
await new Promise((resolve) => setTimeout(resolve, 200)); await new Promise((resolve) => setTimeout(resolve, 200));
@ -82,11 +83,11 @@ export class RemoteClientLogger {
// check if CloudRunner.isCloudRunnerEnvironment is true, log // check if CloudRunner.isCloudRunnerEnvironment is true, log
if (!CloudRunner.isCloudRunnerEnvironment) { if (!CloudRunner.isCloudRunnerEnvironment) {
const notCloudEnvMessage = `Cloud Runner is not running in a cloud environment, not collecting logs`; const notCloudEnvironmentMessage = `Cloud Runner is not running in a cloud environment, not collecting logs`;
if (CloudRunnerOptions.providerStrategy === 'k8s') { if (CloudRunnerOptions.providerStrategy === 'k8s') {
process.stdout.write(`${notCloudEnvMessage}\n`, 'utf8'); process.stdout.write(`${notCloudEnvironmentMessage}\n`, 'utf8');
} }
CloudRunnerLogger.log(notCloudEnvMessage); CloudRunnerLogger.log(notCloudEnvironmentMessage);
} }
return; return;

View File

@ -63,11 +63,36 @@ describe('Cloud Runner Sync Environments', () => {
value: x.ParameterValue, value: x.ParameterValue,
}; };
}); });
// Apply the same localhost -> host.docker.internal replacement that the Docker provider does
// This ensures the test expectations match what's actually in the output
const endpointEnvironmentNames = new Set([
'AWS_S3_ENDPOINT',
'AWS_ENDPOINT',
'AWS_CLOUD_FORMATION_ENDPOINT',
'AWS_ECS_ENDPOINT',
'AWS_KINESIS_ENDPOINT',
'AWS_CLOUD_WATCH_LOGS_ENDPOINT',
'INPUT_AWSS3ENDPOINT',
'INPUT_AWSENDPOINT',
]);
const combined = [...environmentVariables, ...secrets] const combined = [...environmentVariables, ...secrets]
.filter((element) => element.value !== undefined && element.value !== '' && typeof element.value !== 'function') .filter((element) => element.value !== undefined && element.value !== '' && typeof element.value !== 'function')
.map((x) => { .map((x) => {
if (typeof x.value === `string`) { if (typeof x.value === `string`) {
x.value = x.value.replace(/\s+/g, ''); x.value = x.value.replace(/\s+/g, '');
// Apply localhost -> host.docker.internal replacement for LocalStack endpoints
// when using local-docker or aws provider (which uses Docker)
if (
endpointEnvironmentNames.has(x.name) &&
(x.value.startsWith('http://localhost') || x.value.startsWith('http://127.0.0.1')) &&
(CloudRunnerOptions.providerStrategy === 'local-docker' || CloudRunnerOptions.providerStrategy === 'aws')
) {
x.value = x.value
.replace('http://localhost', 'http://host.docker.internal')
.replace('http://127.0.0.1', 'http://host.docker.internal');
}
} }
return x; return x;

View File

@ -33,6 +33,7 @@ describe('Cloud Runner Caching', () => {
cloudRunnerBranch: `cloud-runner-develop`, cloudRunnerBranch: `cloud-runner-develop`,
cloudRunnerDebug: true, cloudRunnerDebug: true,
}; };
// For AWS LocalStack tests, explicitly set provider strategy to 'aws' // For AWS LocalStack tests, explicitly set provider strategy to 'aws'
// This ensures we use AWS LocalStack instead of defaulting to local-docker // This ensures we use AWS LocalStack instead of defaulting to local-docker
if (process.env.AWS_S3_ENDPOINT && process.env.AWS_S3_ENDPOINT.includes('localhost')) { if (process.env.AWS_S3_ENDPOINT && process.env.AWS_S3_ENDPOINT.includes('localhost')) {

View File

@ -192,6 +192,9 @@ echo "CACHE_KEY=$CACHE_KEY"`;
# Builder doesn't exist, skip post-build (shouldn't happen, but handle gracefully) # Builder doesn't exist, skip post-build (shouldn't happen, but handle gracefully)
echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt
fi fi
# Write "Collected Logs" message for K8s (needed for test assertions)
# Write to both stdout and log file to ensure it's captured even if kubectl has issues
echo "Collected Logs" | tee -a /home/job-log.txt
# Write end markers directly to log file (builder might be cleaned up by post-build) # Write end markers directly to log file (builder might be cleaned up by post-build)
# Also write to stdout for K8s kubectl logs # Also write to stdout for K8s kubectl logs
echo "end of cloud runner job" | tee -a /home/job-log.txt echo "end of cloud runner job" | tee -a /home/job-log.txt
@ -224,6 +227,9 @@ echo "CACHE_KEY=$CACHE_KEY"`;
else else
echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt echo "Builder path not found, skipping post-build" | tee -a /home/job-log.txt
fi fi
# Write "Collected Logs" message for K8s (needed for test assertions)
# Write to both stdout and log file to ensure it's captured even if kubectl has issues
echo "Collected Logs" | tee -a /home/job-log.txt
# Write end markers to both stdout and log file (builder might be cleaned up by post-build) # Write end markers to both stdout and log file (builder might be cleaned up by post-build)
echo "end of cloud runner job" | tee -a /home/job-log.txt echo "end of cloud runner job" | tee -a /home/job-log.txt
echo "---${CloudRunner.buildParameters.logId}" | tee -a /home/job-log.txt`; echo "---${CloudRunner.buildParameters.logId}" | tee -a /home/job-log.txt`;

View File

@ -59,15 +59,15 @@ class Docker {
// Check if host.docker.internal is needed (for LocalStack access from containers) // Check if host.docker.internal is needed (for LocalStack access from containers)
// Add host mapping if any environment variable contains host.docker.internal // Add host mapping if any environment variable contains host.docker.internal
const envVarString = ImageEnvironmentFactory.getEnvVarString(parameters, additionalVariables); const environmentVariableString = ImageEnvironmentFactory.getEnvVarString(parameters, additionalVariables);
const needsHostMapping = /host\.docker\.internal/i.test(envVarString); const needsHostMapping = /host\.docker\.internal/i.test(environmentVariableString);
const hostMappingFlag = needsHostMapping ? `--add-host=host.docker.internal:host-gateway` : ''; const hostMappingFlag = needsHostMapping ? `--add-host=host.docker.internal:host-gateway` : '';
return `docker run \ return `docker run \
--workdir ${dockerWorkspacePath} \ --workdir ${dockerWorkspacePath} \
--rm \ --rm \
${hostMappingFlag} \ ${hostMappingFlag} \
${envVarString} \ ${environmentVariableString} \
--env GITHUB_WORKSPACE=${dockerWorkspacePath} \ --env GITHUB_WORKSPACE=${dockerWorkspacePath} \
--env GIT_CONFIG_EXTENSIONS \ --env GIT_CONFIG_EXTENSIONS \
${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \ ${gitPrivateToken ? `--env GIT_PRIVATE_TOKEN="${gitPrivateToken}"` : ''} \