Files
dokploy/packages/server/src/utils/builders/railpack.ts
T
Mauricio Siu fee802a57b refactor: remove outdated comment in railpack command builder
- Removed a comment regarding the use of shell-quote for escaping export statements, as the functionality is now handled by the `prepareEnvironmentVariablesForShell` function introduced in a previous commit.
2025-11-19 21:18:13 -06:00

113 lines
3.0 KiB
TypeScript

import { createHash } from "node:crypto";
import { nanoid } from "nanoid";
import { quote } from "shell-quote";
import {
parseEnvironmentKeyValuePair,
prepareEnvironmentVariables,
prepareEnvironmentVariablesForShell,
} from "../docker/utils";
import { getBuildAppDirectory } from "../filesystem/directory";
import type { ApplicationNested } from ".";
const calculateSecretsHash = (envVariables: string[]): string => {
const hash = createHash("sha256");
for (const env of envVariables.sort()) {
hash.update(env);
}
return hash.digest("hex");
};
export const getRailpackCommand = (application: ApplicationNested) => {
const { env, appName, cleanCache } = application;
const buildAppDirectory = getBuildAppDirectory(application);
const envVariables = prepareEnvironmentVariablesForShell(
env,
application.environment.project.env,
application.environment.env,
);
// Prepare command
const prepareArgs = [
"prepare",
buildAppDirectory,
"--plan-out",
`${buildAppDirectory}/railpack-plan.json`,
"--info-out",
`${buildAppDirectory}/railpack-info.json`,
];
for (const env of envVariables) {
prepareArgs.push("--env", env);
}
// Calculate secrets hash for layer invalidation
const secretsHash = calculateSecretsHash(envVariables);
const cacheKey = cleanCache ? nanoid(10) : undefined;
// Build command
const buildArgs = [
"buildx",
"build",
...(cacheKey
? [
"--build-arg",
`secrets-hash=${secretsHash}`,
"--build-arg",
`cache-key=${cacheKey}`,
]
: []),
"--build-arg",
`BUILDKIT_SYNTAX=ghcr.io/railwayapp/railpack-frontend:v${application.railpackVersion}`,
"-f",
`${buildAppDirectory}/railpack-plan.json`,
"--output",
`type=docker,name=${appName}`,
];
// Add secrets properly formatted
// Use prepareEnvironmentVariables (without ForShell) to get raw values for parsing
const rawEnvVariables = prepareEnvironmentVariables(
env,
application.environment.project.env,
application.environment.env,
);
const exportEnvs = [];
for (const pair of rawEnvVariables) {
const [key, value] = parseEnvironmentKeyValuePair(pair);
if (key && value) {
buildArgs.push("--secret", `id=${key},env=${key}`);
exportEnvs.push(`export ${key}=${quote([value])}`);
}
}
buildArgs.push(buildAppDirectory);
const bashCommand = `
# Ensure we have a builder with containerd
docker buildx create --use --name builder-containerd --driver docker-container || true
docker buildx use builder-containerd
echo "Preparing Railpack build plan..." ;
railpack ${prepareArgs.join(" ")} || {
echo "❌ Railpack prepare failed" ;
docker buildx rm builder-containerd || true
exit 1;
}
echo "✅ Railpack prepare completed." ;
echo "Building with Railpack frontend..." ;
# Export environment variables for secrets
${exportEnvs.join("\n")}
docker ${buildArgs.join(" ")} || {
echo "❌ Railpack build failed" ;
docker buildx rm builder-containerd || true
exit 1;
}
echo "✅ Railpack build completed." ;
docker buildx rm builder-containerd
`;
return bashCommand;
};