QA1 테스트 저장소
퇴역 (2026-09-15, 오너 지시 #1659) — v0.19.3 출시부터 QA1은 앱 워크플로 어디서도 자동 실행되지 않는다. 앱의
qa1.lock.json·scripts/qa1.mjs·.github/actions/prepare-qa1·QA1 npm 훅과 QA1 기반 잡(단위·브라우저·viewport·e2e-evidence·배포 smoke·prod-smoke·social-login 일일 점검)은 제거됐다. 제품 계약 검증은 QA2 승격 게이트가 맡는다. 아래는 이관 당시 기록이다.
2026-09-14 사용자 결정. 기존 앱 Full CI 테스트 전체를 비공개 dekerd/Barbelic-QA1로 옮긴다. 앱 작업은 #1591, QA1 이관은 #1에서 추적한다. 설명·정책·운영 문서의 정본은 이 문서 저장소에 둔다.
목적과 범위
테스트의 원본을 제품 코드와 별도로 수정·관리하면서 기존 정적·단위·DB·브라우저·화면 검사의 동작과 실행 범위를 보존한다. 일부 대표 테스트만 옮기는 작업이 아니다. 이관 기준 앱 커밋에서 Full CI가 사용하는 테스트, fixture, helper, 검사 전용 실행기와 설정을 모두 대상에 포함한다. 기존 제외·skip 정책을 이관을 이유로 바꾸거나 케이스를 새로 제외하지 않는다.
| 저장소 | 소유하는 내용 |
|---|---|
dekerd/Barbelic | 제품 소스·공통 백엔드·DB 마이그레이션·빌드·배포·릴리스 통합, 사용할 QA1 버전을 고정하는 qa1.lock.json과 호출 코드 |
dekerd/Barbelic-QA1 | 기존 Full CI 테스트·fixture·helper·검사 전용 실행기와 설정, 이관 대상 목록과 검증 대상 앱 실행 도구 |
dekerd/Barbelic-docs | 테스트 명세·품질 기준·운영 방법·결정·검증 및 업데이트 보고 |
QA1은 기존 앱 테스트의 소유권을 옮긴 저장소다. QA2는 별도의 독립 검증으로 유지하며 QA2의 구현·예상값·결과를 QA1의 것으로 합치지 않는다. 다른 작업자의 미반영 변경은 임의로 가져오지 않으며, 이관 기준 커밋과 후속 테스트 변경을 구분한다.
파일 배치와 실행 경계
QA1은 suite/<기존 앱 상대경로>에 원본을 둔다. 예를 들어 앱에서 tests/에 있던 파일은 QA1의 suite/tests/에 위치한다. 이 배치는 테스트가 참조하는 앱 소스·SQL·기존 helper 간 상대경로를 검사 실행 시 보존하기 위한 것이다. 테스트 내부의 import를 한꺼번에 바꾸면서 생기는 별도 동작 변경을 줄인다.
앱의 scripts/qa1.mjs는 qa1.lock.json에 지정한 QA1 커밋과 suite tree를 확인하고, 검사에 필요한 파일을 앱 작업 트리의 기존 상대경로에 준비한다. 준비한 파일은 앱 Git의 추적 대상에서 제외하고 QA1 원본에서 관리한다. 앱에서 같은 경로의 파일이 보인다는 사실은 원본이 앱 저장소에 남아 있다는 뜻이 아니다.
준비 과정은 앱이 추적하는 제품 파일이나 사용자가 수정한 파일을 덮어쓰지 않아야 한다. 충돌·버전 불일치·QA1 접근 실패는 준비 실패이며, 빈 테스트 목록을 성공으로 처리하지 않는다. 준비한 파일을 앱에 다시 커밋하거나 충돌을 피하려고 사용자의 수정 파일을 삭제하지 않는다.
앱 소스·DB 마이그레이션·빌드와 배포 설정은 계속 앱에서 읽는다. QA1이 앱의 제품 파일을 복제해 두거나 자체 마이그레이션 정본을 갖지 않는다. DB 검사는 검증 대상 앱의 마이그레이션으로 만든 격리 DB에 대해 실행하며 사용자 원본 데이터의 수정·이관 권한은 달라지지 않는다.
버전 고정과 결과 식별
앱의 qa1.lock.json은 schemaVersion: 1, repository: "dekerd/Barbelic-QA1", 40자리 commit과 suiteTree를 모두 요구한다. 이동하는 브랜치 이름만으로 검사를 선택하지 않는다. QA1 독립 CLI도 앱의 lock과 다른 QA1 커밋으로 실행하는 것을 거부한다. 검증 대상 앱 checkout은 아래 명령에 절대경로로 지정하며, 결과에 실제 앱 커밋과 tree를 기록한다. 결과를 설명하거나 재현할 때 다음 입력을 함께 식별한다.
- 앱 후보 커밋과 Git tree, 작업 트리에 추가 변경이 있었는지.
- QA1 커밋과 suite tree, 실행한 검사 묶음 및 인자.
- Node·패키지 잠금·DB·브라우저 등 실행에 관련된 환경 버전과 설정.
- 결과·로그·산출물 위치, 전체/성공/실패/skip/미실행 수와 미검증 범위.
앱 후보가 같더라도 QA1 버전이 달라지면 검증 입력이 달라진다. 이전 조합의 성공을 새 테스트 버전의 성공으로 쓰지 않는다. 부분 검사, 문서 검사, 파일 동일성 확인은 Full CI 통과와 별개다. 기존 Full 결과 재사용은 CI 절차의 조건과 함께 이 버전 조합을 확인한다.
준비 상태와 파일별 hash 장부는 앱 Git 디렉터리의 qa1/state.json에 둔다. 앱 루트에서 git rev-parse --git-path qa1/state.json으로 실제 경로를 확인한다. 별도 worktree에서는 .git/이 디렉터리가 아닐 수 있으므로 경로를 직접 가정하지 않는다.
run CLI의 실행 식별 기록은 앱 checkout의 test-results/qa1/<timestamp>-<pid>.json이다. appCommit, appTree, appDiffSha256, qa1Commit, qa1SuiteTree, node, platform, script, arguments, startedAt, finishedAt, exitCode, integrityError를 기록한다. 이는 검사 실행 전후의 후보·준비 파일 변경 여부와 종료 결과를 식별하는 기록이다. 개별 테스트 수와 DB·브라우저 환경 등은 해당 검사 로그와 함께 확인한다. 기존 npm 명령을 직접 실행했을 때의 결과 및 로컬 CI 산출물 위치는 기존대로 유지하며, 그 실행에도 이 CLI 기록이 자동 생성된다고 가정하지 않는다.
로컬 검사와 원격 실행
앱에서 사용하는 기존 npm run check, npm run ci:precheck-local -- --release origin/release/vX.Y.Z, npm run ci:full-local -- --only <단계>의 진입점과 부분 실행 범위를 유지한다. 앱의 npm 사전 실행 코드가 고정한 QA1 파일을 준비한 후 해당 검사를 실행한다.
앱 checkout에서 준비·상태 확인·실행용 파일 정리를 직접 할 때는 다음 명령을 사용한다. qa1:clean은 준비한 파일의 변경 여부를 확인하며 사용자가 수정한 파일을 강제로 지우는 용도로 쓰지 않는다.
npm run qa1:prepare
npm run qa1:status
npm run qa1:clean검사와 함께 QA1 실행 식별 기록을 남기려면 앱 checkout에서 다음과 같이 호출한다. 브라우저 예시는 기존 부분 실행이며 Full 성공을 뜻하지 않는다.
node scripts/qa1.mjs run check
node scripts/qa1.mjs run ci:full-local -- --only browserQA1 checkout에서는 다음과 같이 앱을 지정한다. <앱 checkout 절대경로>는 이관 후 앱 코드가 준비·커밋되고 필요한 의존성과 해당 검사 환경을 갖춘 checkout으로 바꾼다. QA1 checkout의 커밋은 그 앱의 lock에 고정한 커밋과 일치해야 한다.
node bin/qa1.mjs run --app "<앱 checkout 절대경로>" check
node bin/qa1.mjs run --app "<앱 checkout 절대경로>" ci:full-local -- --only browserQA1 루트의 npm run check는 이관 manifest의 파일 hash를 검증하고 새 runner 자체의 회귀 검사를 수행한다. 위 명령으로 앱의 check를 실행하는 것과 범위가 다르며 앱 Full CI를 실행하지 않는다. 이관 파일을 의도적으로 조정하면 migration-adaptations.json에 새 hash와 이유를 기록하고 초기 원본의 동일성 확인과 구분한다.
로컬 Git 객체 공급원을 사용하려면 앱 실행 환경의 BARBELIC_QA1_SOURCE에 QA1 저장소 경로를 지정한다. 이 변수는 그 저장소의 현재 작업 파일을 가져오라는 의미가 아니다. 해당 저장소에 앱이 고정한 커밋의 Git 객체가 있으면 HEAD가 다른 커밋이어도 고정 커밋을 가져오며, 미커밋 파일은 사용하지 않는다.
QA1은 비공개 저장소이므로 실행 환경에서 해당 커밋을 읽을 수 있어야 한다. QA1 읽기 전용 deploy key와 앱의 QA1_DEPLOY_KEY secret을 설정했다. 인증 정보는 실행 환경의 비밀 설정으로 공급하며 앱의 배포 산출물·브라우저 코드·결과 로그에 넣지 않는다. 이 설정은 원격 검사의 실행·통과 증거가 아니다.
일반적인 저장소 생성·이관 요청 자체는 원격 CI의 실행이나 무제한 재실행 승인이 아니다. 수동 실행뿐 아니라 자동 CI를 일으키는 push·PR·승격 후보 갱신도 기존 사용자 승인 경계를 따른다. 이관 당시 앱의 admin-backend-fixture workflow는 모든 브랜치 push에서 발화하므로 앱 브랜치 게시도 이 경계에 포함된다. 원격에서만 확인할 수 있는 범위는 미실행 이유와 함께 남긴다. 실패 수리는 Full CI 실패 수리 절차에 따라 관련 묶음을 로컬에서 확인한다.
2026-09-14 후속 사용자 지시 “아니 관리자 권한으로 그냥 바로 반영해줘”에 따라 이번 QA1 이관은 관리자 권한으로 직접 반영하는 예외를 적용한다. 이 승인은 이번 이관 반영에 한정하며 상시 원격 CI·재실행 정책이나 다른 작업의 승인 경계를 바꾸지 않는다. 실제 main 반영과 자동 실행 결과는 이관 업데이트 리포트에서 구분한다.
준비 중단 후 복구
준비 작업을 중단한 뒤 state.json.lock이 남아 있으면 그 파일의 pid가 가리키는 프로세스가 확실히 종료했는지 먼저 확인한다. 실행 중이거나 소유 프로세스의 상태가 불명확하면 잠금을 제거하지 않는다. 종료를 확인한 경우 실제 Git 디렉터리 안의 해당 state.json.lock만 제거하고 원래 고정 버전으로 npm run qa1:prepare를 재개한다. state.json 장부나 준비된 전체 디렉터리를 지우지 않으며 로컬 수정 파일을 보존한다. 파일 충돌로 재개가 거부되면 변경을 보존한 상태에서 원본과 준비 상태를 확인한다.
테스트를 변경할 때
테스트·fixture·helper·검사 전용 실행기는 QA1의 suite/ 원본에서 수정한다. 앱에 준비된 실행용 파일을 직접 수정한 채 결과를 고정된 QA1 커밋의 검증으로 보고하지 않는다. QA1 변경을 앱 검증에 채택하려면 앱의 고정 버전을 갱신하고 두 변경을 연결해 기록한다. 앱과 테스트 변경이 함께 필요하면 양쪽 후보 버전을 명시해 관련 로컬 검사를 수행한다.
QA1에 테스트를 게시했다는 사실만으로 모든 앱 브랜치의 테스트 버전이 바뀌지 않는다. 같은 이유로 앱의 lock 변경만으로 원격 검사 통과나 배포가 완료되지 않는다. 이전 조합으로 복구할 때도 앱과 호환되는 QA1 고정 버전을 사용하며 그 조합의 검증 상태를 확인한다.
이관 완료 판단과 현재 상태
완료 판단에서는 이관 기준 앱의 대상 목록과 QA1 파일을 대조하고, 앱에서 추적하는 테스트 원본이 남지 않았는지 확인한다. 변경 없이 옮긴 파일의 동일성과 의도적으로 조정한 실행 연결을 구분한다. 기존 검사 목록·부분 실행·준비 충돌 거부·앱과 QA1 버전 식별을 확인하고, 실행하지 못한 검사는 명시한다.
2026-09-14 확인 상태는 다음과 같다. 실행별 후보·전체/성공/실패/skip/미실행 수와 최종 precheck·반영 결과는 앱 #1591과 QA1 #1의 최종 리포트를 확인한다.
| 항목 | 확인된 상태 |
|---|---|
| 이관 원본 | 앱 1711ae2e84612d8af868670a65ef3b0c48957817 기준 1,210개 파일 동일성 및 이관 후 앱 추적 원본 0개 확인 |
| QA1 원격 | main 6db676c3b1db888cea1ac9eb9d824b53535d72f9 게시, suite tree 232316548699888ee2359cca04710c5ff8c64553 |
| runner 회귀 검사 | 복구와 병렬 준비 잠금 충돌을 수리한 뒤 17/17 통과 |
| 앱 로컬 검사 | npm run check 전후 결과 동일, 브라우저 저장·복구 118/118 통과·skip 0. 첫 precheck의 준비 충돌을 수리한 뒤 앱 9a37e73c·QA1 6db676c3에서 --release origin/main 최종 로컬 precheck 4묶음 모두 통과. 단위 3,799성공·148기존 skip, DB Node 107/107, pgTAP 122파일·2,444단언 PASS. 실제 목적 release 검증·원격 Merge Check와는 구분 |
| 분류 장부 | QA1 준비 상태의 files를 포함하도록 연결해 이관 파일 전부를 집계. 기준선 대비 새 미분류·등록 누락 증가 없음. 기존 main의 분류 부채는 이번 이관 수리로 확대하지 않음 |
| 비공개 접근 설정 | QA1 읽기 전용 deploy key와 앱 QA1_DEPLOY_KEY secret 설정. 원격 CI 실행 확인과 구분 |
| 앱 반영 | 이번 이관의 관리자 직접 반영 승인에 따라 main 9a37e73c3a6eae6ccd8e3c8caffe29f575eb1777 게시 확인. 보호 설정 변경·force 없이 기존 main에서 fast-forward. 문서 반영 커밋과 자동 실행 결과는 업데이트 리포트 및 담당 이슈에서 추적 |
앱 최종 로컬 검증과 원격 반영은 구분해 추적한다. QA1 원본 게시·부분 검사 성공·문서 작성만으로 Full CI 통과 또는 앱·문서의 원격 반영과 운영 적용이 완료된 것으로 판단하지 않는다.