Skip to content

Commit 50da0db

Browse files
committed
Fixing coolify caching issues
1 parent 5f649e1 commit 50da0db

1 file changed

Lines changed: 40 additions & 10 deletions

File tree

crates/harness-api/src/handlers.rs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3518,12 +3518,38 @@ pub async fn deploy_to_hosting(
35183518
// forced (no-cache) rebuild so the in-Dockerfile clone re-fetches the latest commit.
35193519
// If the app was deleted in Coolify (404), drop the stale mapping and fall through to
35203520
// create a fresh one — so a user who wipes the app in Coolify can just redeploy.
3521-
//
3522-
// NOTE (config drift): a redeploy reuses the app config Coolify stored at create time
3523-
// (Dockerfile, ports_mappings, etc.). Changes to how Monastery *generates* those won't
3524-
// reach an existing app via redeploy — the user must delete the app in Coolify and
3525-
// redeploy (404 path) to pick them up. TODO: PATCH the app config on redeploy to sync.
35263521
if let Some(existing_uuid) = lookup_deployment(&state, req.project_id, req.connection_id).await? {
3522+
// Refresh the app's stored Dockerfile FIRST. A Coolify redeploy rebuilds from the
3523+
// Dockerfile it saved at create time; because that Dockerfile was byte-identical
3524+
// every redeploy, the `git clone` layer stayed cached and the app kept serving the
3525+
// code from its first build. Re-sending a freshly-generated Dockerfile (new
3526+
// embedded cachebust) changes the clone layer's cache key so `force=true` actually
3527+
// re-clones the latest commit. Best-effort: if the update fails we still trigger the
3528+
// forced rebuild below (no worse than before).
3529+
let dockerfile_b64 = base64::engine::general_purpose::STANDARD.encode(clone_dockerfile.as_bytes());
3530+
let patch_url = format!("{}/api/v1/applications/{}", base, existing_uuid);
3531+
match client
3532+
.patch(&patch_url)
3533+
.header("Authorization", format!("Bearer {}", api_token))
3534+
.header("Content-Type", "application/json")
3535+
.json(&serde_json::json!({ "dockerfile": dockerfile_b64 }))
3536+
.send()
3537+
.await
3538+
{
3539+
Ok(r) if r.status().is_success() => {
3540+
tracing::info!("Refreshed Coolify Dockerfile for app {} before redeploy", existing_uuid);
3541+
}
3542+
Ok(r) => {
3543+
tracing::warn!(
3544+
"Coolify Dockerfile refresh returned HTTP {} — redeploying with force anyway",
3545+
r.status().as_u16()
3546+
);
3547+
}
3548+
Err(e) => {
3549+
tracing::warn!("Coolify Dockerfile refresh request failed ({}) — redeploying with force anyway", e);
3550+
}
3551+
}
3552+
35273553
let deploy_url = format!("{}/api/v1/deploy?uuid={}&force=true", base, existing_uuid);
35283554
match client
35293555
.get(&deploy_url)
@@ -4276,15 +4302,19 @@ fn generate_clone_dockerfile(
42764302
branch: &str,
42774303
) -> (String, u16) {
42784304
let cachebust = chrono::Utc::now().timestamp();
4279-
// Clone step for node-based stages (git installed via apk).
4305+
// The cachebust is embedded DIRECTLY in the clone RUN command (not just as an `ARG`) so the
4306+
// layer's cache key changes every time the Dockerfile is regenerated — forcing Docker to
4307+
// re-run `git clone` and fetch the latest commit. An `ARG` alone does NOT work: Docker only
4308+
// busts cache at a build-arg's first *usage*, and the old Dockerfile never referenced it, so
4309+
// the clone layer was cached and redeploys kept shipping the code from the first build.
42804310
let node_clone = format!(
4281-
"RUN apk add --no-cache git && git -c http.sslVerify=false clone --depth 1 --single-branch --branch {b} \"{u}\" . && rm -rf .git",
4282-
b = branch, u = clone_url
4311+
"RUN apk add --no-cache git && echo \"monastery-cachebust {cb}\" && git -c http.sslVerify=false clone --depth 1 --single-branch --branch {b} \"{u}\" . && rm -rf .git",
4312+
cb = cachebust, b = branch, u = clone_url
42834313
);
42844314
// Clone step for the prebuilt alpine/git image (git already present).
42854315
let git_clone = format!(
4286-
"RUN git -c http.sslVerify=false clone --depth 1 --single-branch --branch {b} \"{u}\" . && rm -rf .git",
4287-
b = branch, u = clone_url
4316+
"RUN echo \"monastery-cachebust {cb}\" && git -c http.sslVerify=false clone --depth 1 --single-branch --branch {b} \"{u}\" . && rm -rf .git",
4317+
cb = cachebust, b = branch, u = clone_url
42884318
);
42894319

42904320
match framework {

0 commit comments

Comments
 (0)