Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 71 additions & 21 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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: 일반적인 새 릴리즈
Expand All @@ -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이 설정되어 있어야 합니다:
Expand All @@ -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. 원격 저장소 접근 권한 확인
72 changes: 59 additions & 13 deletions .github/workflows/force-rebuild.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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: |
Expand All @@ -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:
Expand Down Expand Up @@ -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
42 changes: 21 additions & 21 deletions .github/workflows/retag-release.yaml
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand All @@ -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: |
Expand Down Expand Up @@ -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:
Expand All @@ -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