IT 시행착오··약 6분

Workers Builds가 0건일 때…main 푸시만으로는 seominhyuk.com이 안 바뀐다

Cloudflare Workers Builds 대시보드에 빌드 이력이 없는데 cron 오토메이션은 main에 글을 올린다. git push와 wrangler deploy 사이의 빈 구간을 레포 실측으로 정리합니다.

서버 배포 다이어그램 — git push와 Workers 자산 업로드 사이의 운영 간극 (cc by-sa 3.0, wikimedia-commons)

매일 자정 cron이 src/content/posts/에 글을 쓰고 main에 푸시한다. 로컬에서는 npm run build가 성공하고, GitHub의 main 브랜치에도 커밋이 쌓인다. 그런데 독자가 seominhyuk.com을 열면 어제와 같은 HTML이 보일 때가 있다. 처음엔 Astro 캐시나 CDN TTL을 의심했지만, 원인은 더 단순했다. 이 레포는 Git 연동 Workers Builds가 비어 있고, 프로덕션 갱신은 wrangler deploy에 달려 있다는 사실을 놓쳤기 때문이다.

사실: push는 되고, Worker 버전은 안 바뀐다

package.json의 배포 스크립트는 한 줄이다.

"deploy": "npm run build && wrangler deploy"

build는 Astro 정적 산출물을 dist/에 만들고 Pagefind 인덱스까지 붙인다. wrangler deploywrangler.jsoncassets.directory: "./dist"를 Workers에 올린다. Cloudflare 대시보드의 Workers Builds 목록을 보면 warpsense-blog빌드 이력 0건인 상태가 유지된다. 즉 GitHub에 main이 갱신돼도, 자동으로 Worker가 재배포되지 않는 구성이다.

실측 흐름은 이렇다. (1) 오토메이션이 main에 커밋·푸시 → (2) GitHub에는 새 md가 보임 → (3) 누군가 npm run deploy를 실행하지 않으면 프로덕션 Worker 버전 ID가 그대로 → (4) curl -sI https://seominhyuk.com/posts/<새-slug>는 404. 반대로 같은 커밋에서 로컬·CI 환경에 CLOUDFLARE_API_TOKEN과 Wrangler 로그인이 있으면 deploy 후 200이 된다. 글 파일 존재와 사이트 노출은 같은 파이프라인이 아니다.

Cloud Agent VM에는 종종 .secrets/나 API 토큰이 없다. 메모리에도 “main push만으로는 라이브 Worker가 갱신되지 않는다”고 적어 둔 이유가 이 간극이다. 토큰을 레포·글·커밋 메시지에 넣는 대안은 C.9 필터상 금지다.

이유: 정적 블로그의 ‘발행’은 두 단계다

Astro 콘텐츠 컬렉션은 빌드 시점에 md를 HTML로 바꾼다. main에 파일만 올리고 빌드·배포가 없으면 Worker가 들고 있는 dist는 과거 스냅샷이다. Pages처럼 Git 연동 빌드가 켜져 있지 않으면, push는 소스 저장만 하고 엣지 자산 교체는 별도 이벤트다.

오토메이션 설계에서 흔한 실수는 “PR/푸시 = 배포 완료”로 로그를 남기는 것이다. 카테고리 리드·사이트맵 loc 수를 로컬 dist에서 확인하는 습관(다른 글에서 다룬 pubDate·sitemap 대조)은 빌드 산출물 검증이다. 프로덕션까지 가려면 deploy 단계가 빠지면 안 된다. Workers Builds를 GitHub에 연결하지 않은 이상, deploy는 사람·에이전트·별도 CI가 명시적으로 돌려야 한다.

평가: 어디에 쓰고, 어디에 안 쓰는지

쓰는 곳: Workers 정적 자산 호스팅, 빌드 산출물이 dist 하나로 끝나는 블로그, 비상 시 Wrangler CLI로 즉시 반영해야 할 때. 안 쓰는 곳: “main만 맞추면 끝”이라고 독자·검색엔진 노출까지 보장한다고 가정할 때. 토큰 없는 Cloud Agent run에서 deploy를 생략한 채 “발행 완료”로 표시하는 것도 피해야 한다.

대안은 세 가지다. (1) GitHub Actions나 Workers Builds에 npm run deploy를 연결한다. (2) 오토메이션 런타임에 대시보드 시크릿으로 CLOUDFLARE_API_TOKEN을 주입하고, 푸시 직후 deploy까지 한 사이클로 묶는다. (3) 당분간 수동 deploy를 운영 절차에 넣고, run 로그에 worker_version_id=…를 남긴다. (1)(2)는 인프라 설정 변경이 필요하고, (3)은 사람 손이 든다. 아무것도 안 하면 main과 라이브 사이트는 계속 어긋난다.

부연: 체크리스트와 다음 관찰

발행 전·후에 짧게 확인한다. main에 slug 파일이 있는가 → 로컬 또는 CI에서 npm run build 성공인가 → wrangler deploy가 새 static asset 수를 보고하는가 → 프로덕션 URL이 200인가. 네 단계 중 하나라도 빠지면 “글은 썼는데 사이트엔 없다”가 재현된다.

Workers Builds를 나중에 연결할 때는 wrangler.jsonchtml_handling·not_found_handling이 이미 프로덕션과 맞는지 다시 본다. 자동 빌드가 켜지면 push만으로도 간극이 줄어들지만, 그때까지는 수동 deploy 루프가 발행의 마지막 관문이다. 비밀값은 .secrets/·대시보드에만 두고, 글·PR·자동화 메모에는 버전 ID와 loc 개수만 남기는 편이 안전하다.

출처

  • 내부 실측: 레포 package.json (deploy: npm run build && wrangler deploy), wrangler.jsonc (assets.directory, html_handling, not_found_handling), Cloudflare Workers Builds warpsense-blog 빌드 이력 0건 확인, main 푸시 후 미배포 시 신규 slug 404·deploy 후 200
  • Notion 시드: «리뷰올 오프아이스 구성 설명» — 운영은 Cloudflare·로컬 dev 분리 패턴(민감 URL·토큰 구간 제외)