Laravel PackageManifest 는 bootstrap/cache/packages.php 가 있으면 stale 여부를 검사하지
않고 그대로 읽어 등재된 provider 를 new 한다. 코어 업데이트는 Step 6/8 에서 vendor 를
--no-dev 로 교체하지만 그 파일은 Step 11 까지 이전 설치본의 것이 남으므로, 옵션 없는
`composer install` 로 깔린 사이트에서는 Step 10 spawn 자식이 새 vendor 에 없는 provider 를
찾다 부팅 단계에서 죽는다. 부팅 전이라 앱 로그에 흔적이 없고 부모에게는 자식의 비정상
종료로만 보여, 운영자에게는 「Class ... not found」 와 수동 재개 안내만 남는다.
(sir.kr 커뮤니티 제보, 7.0.9 → 7.0.10)
3계층으로 막는다.
1. 부모 — spawn 직전 PackageManifestCacheHelper::clear
2. 자식 — bootstrap/app.php 가 G7_UPDATE_IN_PROGRESS 를 보고 스스로 정리한다.
이미 배포된 7.0.9·7.0.10 부모는 고칠 수 없으므로 그 아래에서 도는 신버전
자식의 유일한 방어다. App\ 클래스를 참조하지 않고 실패는 무시한다.
3. 범위 — CoreVersionChecker 의 env APP_VERSION 우선을 CoreUpdateContext 트리 안으로
축소한다. 업데이트 전에 뜬 artisan serve·큐 워커가 옛 값을 물고 확장을
incompatible_core 로 끄던 경로를 닫는다(관리자 템플릿이 대상이면 복구 UI
자체에 도달할 수 없다).
업데이트 트리 판정은 App\Support\CoreUpdateContext 가 단독 소유하고
CoreServiceProvider::isCoreUpdateInProgress 는 위임으로 남는다. bootstrap/app.php 의
복제본은 부팅 전이라 불가피한 예외이며, 두 조건의 동형성을 테스트가 단언한다.
실측 중 드러난 결함 2건을 함께 고쳤다.
- ConfigCacheHelper::withPreservedContainer 가 파사드 애플리케이션을 되돌리지 않아
Step 11 이 `Target class [command.tinker] does not exist` 로 실패·롤백했다.
- updateVersionInEnv 가 프로세스 환경을 갱신하지 않아 config 캐시에 이전 버전이 구워졌다
(Laravel env 저장소가 불변이라 재부팅으로도 덮이지 않는다).
인스톨러는 재사용 vendor 의 개발용 패키지를 installed.json 으로 감지해 설치 환경 확인
카드·설치 로그로 알리되 설치를 차단하지 않고( 결정 D1), 재사용 경로에서도 컴파일 캐시를
정리한다. 실행되는 명령만이 아니라 실패 시 안내하는 수동 명령까지 --no-dev 로 맞췄다.
코어 업데이트 완료·핸드오프·단독 재개 사후 단계에서 queue:restart 신호를 보낸다(D3).
코어 7.0.10 → 7.0.11.
7.0.9 → 7.0.10 sudo 업데이트 실측 후 점검에서 드러난 3건.
- 정리 단계가 소스 경로(core_{ts}/extracted/{루트}) 안쪽만 지워 껍데기가
업데이트마다 남던 것을 격리 디렉토리 루트째 삭제로 바꾼다. 부모는 구버전
클래스로 돌아 다음 업데이트부터 효력이 있으므로, 신버전 코드로 도는 두 자식
(execute-upgrade-steps / execute-bundled-updates)이 파일이 없는 core_* 만
골라 치운다 — 구버전 부모에서 올라오는 업데이트도 껍데기 없이 끝난다.
- 항목별 소유권 스냅샷이 격리 디렉토리 생성 뒤에 찍혀 root 가 만든 추출본을
원본으로 기록하고 복원이 다시 root 로 되돌리던 것을, 이번 실행의 격리
디렉토리를 스냅샷에서 제외해 닫는다.
- 완료 안내문이 성공 경로에서는 동작하지 않는 hotfix:rollback-stale-files 를
가리키던 것을 --prune 재실행 안내만 남기도록 정정한다(ko/en/ja).
부수: ExecuteUpgradeStepsStandaloneTest 가 앞선 core:update 실행이 남긴
프로세스 env 플래그에 따라 결과가 갈리던 순서 의존을 setUp/tearDown 에서 제거.
7.0.9 클린 설치본에서 7.0.10 으로 올리자 업그레이드 스텝 단계가 "부모 메모리 stale" 로 중단됐다.
스텝 자식은 부모가 비우지 않은 이전 버전 config 캐시로 부팅해 env APP_VERSION 오버라이드와
신버전 config/app.php 의 update 목록을 모두 보지 못한다. 이전 릴리즈에서는 자식 진입부의
config:cache 가 전역 Container 를 일회용 앱으로 바꿔 놓는 부수효과로 가드가 우연히 침묵했고,
그 부수효과를 걷어낸 withPreservedContainer 가 잠복 결함을 드러냈다.
- stale 가드는 CoreVersionChecker::getCoreVersion(env 우선) 으로 판독
- 부모는 spawn 직전 config 캐시를 비우고, 자식은 캐시 파일이 있으면 디스크 config 를 직접 읽는다
(7.0.10 이 추가한 public/build/ext 쓰기 권한 정상화 누락 차단)
- route:cache 도 같은 부수효과를 남기므로 RouteCacheHelper·optimizeSystem 을 보존 래퍼로 감쌌다
(단독 스텝 재실행·시스템 최적화 뒤 정적 재게시 예약 소실)
- 과거 업그레이드 사고 14부류를 7.0.10 변경과 대조 — 재발 조건은 위 3건뿐
- audit 룰 fresh-app-artisan-call-outside-cache-helper + 픽스처, 회귀 테스트 6건(수정 전 red)
확장이 훅으로 등록한 카탈로그에서 고른 값은 그 확장이 사라져도 저장값으로 남는다.
그 상태에서 값만 보고 판정하면 이미 제공 불가한 항목이 사용자 화면에 그대로 노출된다.
예외도 경고도 로그도 남지 않아 관리자 화면과 나란히 보지 않으면 드러나지 않는다.
- 결제수단에 지정한 PG, 현금영수증 발급사, 검색엔진 드라이버 세 축에 같은 판정을 적용.
공개 응답에서는 제거하고 관리자 응답에는 표시를 남긴다 — 운영자가 고쳐야 할 대상이라
감추면 복구 경로가 사라진다. 서버 검증도 같은 판정을 공유해 화면 우회 제출을 막는다.
- 설정 단건 저장이 벌크 저장과 다른 경로를 타던 문제를 코어·이커머스·게시판에서 정리.
저장은 성공하고 파생 값만 갱신되지 않아 어느 화면에서 저장했느냐로 결과가 갈렸다.
- 단건 저장의 값 형태 계약 신설. 빈 값으로 되돌릴 수 있게 하고, 타입은 defaults.json 의
기본값을 SSoT 로 삼는다. 해석 불가한 입력은 조용히 캐스팅하지 않고 거절한다.
- 드라이버 셀렉트를 서버 카탈로그에 바인딩하고, 저장값이 카탈로그에 없으면 그 값을
드러내는 안내를 8곳 전수에 붙인다. 종전에는 빈 칸으로만 보여 무엇이 저장됐는지
알 수 없었다.
시나리오 매니페스트 8종을 면제 없이 신설했다. `audit:allow` 는 cross product 와 effects
검사를 함께 끄므로, 면제가 걸린 매니페스트에 선언을 추가하면 검증이 회복되지 않는다.
그 아래에서 대응 테스트가 없는 effect 이름 2건이 살아남아 있었고, 함께 정리했다.