diff --git a/.github/workflows/README.md b/.github/workflows/README.md index a170a3e..8278222 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -18,54 +18,73 @@ ## 새로운 워크플로우 -### 3. Retag Release +### 3. Rebuild Docker Image - **파일**: `retag-release.yaml` - **트리거**: 수동 실행 (`workflow_dispatch`) -- **기능**: 기존 태그를 삭제하고 최신 커밋으로 재생성 +- **기능**: 기존 Git 태그 위치는 그대로 유지하고 Docker 이미지만 재빌드 #### 사용법: 1. GitHub 리포지토리의 **Actions** 탭으로 이동 -2. **Retag Release** 워크플로우 선택 +2. **Rebuild Docker Image** 워크플로우 선택 3. **Run workflow** 버튼 클릭 4. 입력값 설정: - - `tag_name`: 재생성할 태그명 (예: `v0.4.0`) - - `confirm_deletion`: `DELETE` 입력 (확인용) + - `tag_name`: 재빌드할 태그명 (예: `v0.4.0`) + - `confirm_rebuild`: `REBUILD` 입력 (확인용) + +#### 특징: +- ✅ **Git 태그 위치 유지**: 기존 커밋 위치 그대로 유지 +- ✅ **Docker 이미지만 재빌드**: 같은 코드로 새로운 이미지 생성 +- ✅ **안전한 작업**: Git 히스토리에 영향 없음 +- ✅ **Digest 충돌 해결**: 기존 Docker 이미지만 삭제 -#### 주의사항: -- ⚠️ **기존 태그가 완전히 삭제됩니다** -- Docker Hub에서 해당 태그의 모든 이미지가 제거됩니다 -- 삭제 후 30초 대기 후 새 이미지 빌드 시작 +#### 사용 시기: +- Docker Hub에서 같은 태그에 여러 digest가 존재할 때 +- Docker 이미지 빌드 과정에서 문제가 있었을 때 +- Git 태그 위치는 유지하되 Docker 이미지만 새로 만들고 싶을 때 -### 4. Force Rebuild Tag +### 4. Move Tag to Latest Commit ⚠️ - **파일**: `force-rebuild.yaml` - **트리거**: 수동 실행 (`workflow_dispatch`) -- **기능**: 기존 태그를 유지하면서 최신 코드로 강제 재빌드 +- **기능**: Git 태그를 현재 HEAD 커밋으로 이동하고 Docker 이미지 재빌드 #### 사용법: 1. GitHub 리포지토리의 **Actions** 탭으로 이동 -2. **Force Rebuild Tag** 워크플로우 선택 +2. **Move Tag to Latest Commit** 워크플로우 선택 3. **Run workflow** 버튼 클릭 4. 입력값 설정: - - `tag_name`: 재빌드할 태그명 (예: `v0.4.0`) - - `force_rebuild`: `REBUILD` 입력 (확인용) + - `tag_name`: 이동할 태그명 (예: `v0.4.0`) + - `confirm_move`: `MOVE_TAG` 입력 (확인용) + +#### ⚠️ 주의사항: +- **Git 태그 위치 변경**: 기존 커밋에서 현재 HEAD로 이동 +- **기존 참조 깨짐**: 기존에 해당 태그를 참조하던 코드/문서가 깨질 수 있음 +- **히스토리 변경**: Git 태그 히스토리가 변경됨 +- **복구 불가**: 한번 실행하면 이전 태그 위치로 복구하기 어려움 #### 특징: -- 기존 태그는 유지됩니다 -- 캐시를 사용하지 않고 완전히 새로 빌드합니다 -- Docker Hub의 태그 충돌 문제를 해결합니다 +- **완전한 재태깅**: Git 태그와 Docker Hub 태그를 모두 삭제 후 재생성 +- **최신 코드 반영**: 현재 HEAD 커밋의 모든 변경사항이 반영됨 +- **소스-이미지 동기화**: Git 태그 위치와 Docker 이미지 내용이 완벽히 일치 + +#### 사용 시기: +- 최신 커밋들을 특정 태그에 반영하고 싶을 때 +- Git 태그 위치 변경이 허용되는 상황일 때 +- 기존 태그 참조를 업데이트할 수 있을 때 ## 문제 해결 시나리오 ### 시나리오 1: Docker Hub에서 같은 태그에 여러 digest 존재 ```bash # 문제: v0.4.0 태그가 두 개의 다른 digest를 가리킴 -# 해결: Retag Release 워크플로우 사용 +# 해결: Rebuild Docker Image 워크플로우 사용 +# 결과: Git 태그 위치는 유지, Docker 이미지만 새로 생성 ``` -### 시나리오 2: 최신 코드가 반영되지 않은 이미지 +### 시나리오 2: 최신 코드를 특정 태그에 반영하고 싶음 ```bash -# 문제: 태그는 최신이지만 이미지 내용이 오래됨 -# 해결: Force Rebuild Tag 워크플로우 사용 +# 문제: 최신 커밋들을 v0.4.0 태그에 반영하고 싶음 +# 해결: Move Tag to Latest Commit 워크플로우 사용 +# 주의: Git 태그 위치가 변경됨 (기존 참조 깨질 수 있음) ``` ### 시나리오 3: 일반적인 새 릴리즈 @@ -75,6 +94,13 @@ git tag v0.4.1 git push origin v0.4.1 ``` +### 시나리오 4: Docker 이미지 빌드 문제 해결 +```bash +# 문제: Docker 이미지 빌드 과정에서 문제 발생 +# 해결: Rebuild Docker Image 워크플로우 사용 +# 결과: 같은 코드로 새로운 Docker 이미지 생성 +``` + ## 필요한 GitHub Secrets 다음 Secrets이 설정되어 있어야 합니다: @@ -88,14 +114,38 @@ git push origin v0.4.1 - **cloud-barista** 조직의 멤버만 워크플로우를 실행할 수 있습니다 - 포크된 리포지토리에서는 실행할 수 없습니다 (보안상의 이유) +## 워크플로우 선택 가이드 + +### 🔄 Rebuild Docker Image vs 🏷️ Move Tag to Latest Commit + +| 상황 | 권장 워크플로우 | 이유 | +|------|----------------|------| +| Docker Hub digest 충돌 | **Rebuild Docker Image** | Git 태그 위치 유지, 안전함 | +| Docker 이미지 빌드 문제 | **Rebuild Docker Image** | 같은 코드로 새 이미지 생성 | +| 최신 커밋을 태그에 반영 | **Move Tag to Latest Commit** | Git 태그 위치 변경 필요 | +| 일반적인 새 릴리즈 | **기존 CD 워크플로우** | 새 태그 생성 (v0.4.1) | + +### ⚠️ Move Tag to Latest Commit 사용 전 체크리스트 + +1. **기존 태그 참조 확인**: 문서, 코드, 다른 프로젝트에서 해당 태그를 참조하는지 확인 +2. **팀 동의**: Git 태그 위치 변경에 대한 팀원들의 동의 +3. **백업**: 필요시 기존 태그 위치 백업 +4. **통지**: 관련 팀원들에게 태그 위치 변경 사전 통지 + ## 트러블슈팅 ### 워크플로우가 실행되지 않는 경우 1. GitHub Secrets 설정 확인 2. 리포지토리 권한 확인 3. 입력값 형식 확인 (태그명은 `v0.4.0` 형식) +4. 확인 코드 정확히 입력 (`REBUILD` 또는 `MOVE_TAG`) ### Docker Hub API 오류 1. Docker Hub 계정 권한 확인 2. API 레이트 리미트 확인 3. 네트워크 연결 상태 확인 + +### Git 태그 관련 오류 +1. 기존 태그가 존재하는지 확인 +2. 태그 삭제 권한 확인 +3. 원격 저장소 접근 권한 확인 diff --git a/.github/workflows/force-rebuild.yaml b/.github/workflows/force-rebuild.yaml index d474470..914a768 100644 --- a/.github/workflows/force-rebuild.yaml +++ b/.github/workflows/force-rebuild.yaml @@ -1,17 +1,17 @@ -# This workflow forces a rebuild of a specific tag without deleting the existing one -# Useful when you want to ensure the latest code is built with an existing tag -name: Force Rebuild Tag +# This workflow moves a Git tag to current HEAD commit and rebuilds Docker image +# WARNING: This changes the Git tag position and may break existing references +name: Move Tag to Latest Commit on: # Manual workflow dispatch with input parameters workflow_dispatch: inputs: tag_name: - description: 'Tag name to rebuild (e.g., v0.4.0)' + description: 'Tag name to move to latest commit (e.g., v0.4.0)' required: true type: string - force_rebuild: - description: 'Force rebuild (type "REBUILD" to confirm)' + confirm_move: + description: '⚠️ WARNING: This will move the Git tag to current HEAD and rebuild Docker image. Type "MOVE_TAG" to confirm' required: true type: string @@ -20,18 +20,19 @@ env: IMAGE_NAME: ${{ github.event.repository.name }} jobs: - force-rebuild: - name: Force Rebuild Tag + move-tag-to-latest: + name: Move Tag to Latest Commit runs-on: ubuntu-22.04 # Only allow if confirmation is provided - if: github.event.inputs.force_rebuild == 'REBUILD' + if: github.event.inputs.confirm_move == 'MOVE_TAG' steps: - name: Checkout source code uses: actions/checkout@v4 with: fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} - name: Validate tag format run: | @@ -42,7 +43,51 @@ jobs: fi echo "Validating tag: $TAG_NAME" - - name: Extract metadata for tag + - name: Delete existing Git tag + run: | + TAG_NAME="${{ github.event.inputs.tag_name }}" + echo "Deleting existing Git tag: $TAG_NAME" + + # Delete local tag if exists + git tag -d $TAG_NAME 2>/dev/null || echo "Local tag $TAG_NAME not found" + + # Delete remote tag if exists + git push origin :refs/tags/$TAG_NAME 2>/dev/null || echo "Remote tag $TAG_NAME not found" + + echo "Git tag $TAG_NAME deleted" + + - name: Delete existing Docker Hub tag + run: | + TAG_NAME="${{ github.event.inputs.tag_name }}" + echo "Deleting existing Docker Hub tag: $TAG_NAME" + + # Delete the tag from Docker Hub + curl -X DELETE \ + -u ${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }} \ + "https://hub.docker.com/v2/repositories/${{ env.DOCKER_REGISTRY_NAME }}/${{ env.IMAGE_NAME }}/tags/$TAG_NAME/" \ + -H "Accept: application/json" 2>/dev/null || echo "Docker Hub tag $TAG_NAME not found" + + echo "Docker Hub tag $TAG_NAME deleted" + + - name: Wait for cleanup + run: | + echo "Waiting 30 seconds for cleanup to complete..." + sleep 30 + + - name: Create new Git tag at current HEAD + run: | + TAG_NAME="${{ github.event.inputs.tag_name }}" + echo "Creating new Git tag: $TAG_NAME at HEAD (${{ github.sha }})" + + # Create new tag at current HEAD + git tag $TAG_NAME + + # Push new tag to remote + git push origin $TAG_NAME + + echo "New Git tag $TAG_NAME created at HEAD" + + - name: Extract metadata for new tag id: meta uses: docker/metadata-action@v5 with: @@ -100,8 +145,9 @@ jobs: - name: Summary run: | - echo "## Force Rebuild Summary" >> $GITHUB_STEP_SUMMARY + echo "## Move Tag to Latest Commit Summary" >> $GITHUB_STEP_SUMMARY echo "- **Tag**: ${{ github.event.inputs.tag_name }}" >> $GITHUB_STEP_SUMMARY echo "- **New Digest**: ${{ steps.docker_build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY - echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY - echo "- **Status**: ✅ Successfully rebuilt" >> $GITHUB_STEP_SUMMARY + echo "- **New Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY + echo "- **Status**: ✅ Successfully moved tag to latest commit" >> $GITHUB_STEP_SUMMARY + echo "- **⚠️ Warning**: Git tag position has been changed!" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/retag-release.yaml b/.github/workflows/retag-release.yaml index 8d87c88..a073e49 100644 --- a/.github/workflows/retag-release.yaml +++ b/.github/workflows/retag-release.yaml @@ -1,17 +1,17 @@ -# This workflow allows manual retagging of existing releases -# It deletes the existing tag from Docker Hub and recreates it with the latest commit -name: Retag Release +# This workflow rebuilds Docker image for existing Git tag without changing tag position +# It deletes the existing Docker image and rebuilds it with the same Git tag position +name: Rebuild Docker Image on: # Manual workflow dispatch with input parameters workflow_dispatch: inputs: tag_name: - description: 'Tag name to retag (e.g., v0.4.0)' + description: 'Tag name to rebuild Docker image (e.g., v0.4.0)' required: true type: string - confirm_deletion: - description: 'Confirm deletion of existing tag (type "DELETE" to confirm)' + confirm_rebuild: + description: 'Confirm Docker image rebuild (type "REBUILD" to confirm)' required: true type: string @@ -20,12 +20,12 @@ env: IMAGE_NAME: ${{ github.event.repository.name }} jobs: - retag-release: - name: Retag Release + rebuild-docker-image: + name: Rebuild Docker Image runs-on: ubuntu-22.04 # Only allow if confirmation is provided - if: github.event.inputs.confirm_deletion == 'DELETE' + if: github.event.inputs.confirm_rebuild == 'REBUILD' steps: - name: Checkout source code @@ -42,18 +42,18 @@ jobs: fi echo "Validating tag: $TAG_NAME" - - name: Delete existing tag from Docker Hub + - name: Delete existing Docker image from Docker Hub run: | TAG_NAME="${{ github.event.inputs.tag_name }}" - echo "Deleting existing tag: $TAG_NAME" + echo "Deleting existing Docker image for tag: $TAG_NAME" - # Delete the tag from Docker Hub + # Delete the Docker image from Docker Hub (Git tag position remains unchanged) curl -X DELETE \ -u ${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }} \ "https://hub.docker.com/v2/repositories/${{ env.DOCKER_REGISTRY_NAME }}/${{ env.IMAGE_NAME }}/tags/$TAG_NAME/" \ -H "Accept: application/json" - echo "Tag $TAG_NAME deleted from Docker Hub" + echo "Docker image for tag $TAG_NAME deleted from Docker Hub" - name: Wait for tag deletion run: | @@ -91,7 +91,7 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build and publish retagged image + - name: Build and publish rebuilt image id: docker_build uses: docker/build-push-action@v6 with: @@ -105,23 +105,23 @@ jobs: cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache - - name: Verify new tag + - name: Verify rebuilt image run: | TAG_NAME="${{ github.event.inputs.tag_name }}" - echo "Verifying new tag: $TAG_NAME" + echo "Verifying rebuilt Docker image for tag: $TAG_NAME" # Wait a bit for Docker Hub to process sleep 10 - # Check if tag exists + # Check if image exists curl -s "https://hub.docker.com/v2/repositories/${{ env.DOCKER_REGISTRY_NAME }}/${{ env.IMAGE_NAME }}/tags/$TAG_NAME/" | jq '.name' - echo "New tag $TAG_NAME successfully created with digest: ${{ steps.docker_build.outputs.digest }}" + echo "Docker image for tag $TAG_NAME successfully rebuilt with digest: ${{ steps.docker_build.outputs.digest }}" - name: Summary run: | - echo "## Retag Summary" >> $GITHUB_STEP_SUMMARY + echo "## Docker Image Rebuild Summary" >> $GITHUB_STEP_SUMMARY echo "- **Tag**: ${{ github.event.inputs.tag_name }}" >> $GITHUB_STEP_SUMMARY echo "- **New Digest**: ${{ steps.docker_build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY - echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY - echo "- **Status**: ✅ Successfully retagged" >> $GITHUB_STEP_SUMMARY + echo "- **Git Tag Position**: Unchanged (same commit)" >> $GITHUB_STEP_SUMMARY + echo "- **Status**: ✅ Successfully rebuilt Docker image" >> $GITHUB_STEP_SUMMARY