1- name : Create branches from issue
2-
3- on :
4- issues :
5- types : [opened]
6-
7- permissions :
8- contents : write
9- issues : write
10-
11- jobs :
12- create_branches :
13- runs-on : ubuntu-latest
14-
15- steps :
16- - name : Checkout repository
17- uses : actions/checkout@v4
18- with :
19- fetch-depth : 0
20- ref : dev # 베이스 브랜치
21-
22- - name : Install Git LFS (for stable git ls-remote)
23- run : |
24- sudo apt-get install git-lfs -y
25-
26- - name : Create feature branch with sequential index if title conflicts
27- env :
28- ISSUE_TITLE : ${{ github.event.issue.title }}
29- ISSUE_NUMBER : ${{ github.event.issue.number }}
30- BASE_BRANCH : dev
31- GH_TOKEN : ${{ github.token }}
32- run : |
33- set -euo pipefail
34-
35- echo "Issue title: $ISSUE_TITLE"
36-
37- # 1. 태그 제거 및 슬러그 생성
38- CLEAN_TITLE=$(echo "$ISSUE_TITLE" | sed 's/^\[[^]]*\][[:space:]]*//')
39- CLEAN_TITLE=$(echo "$CLEAN_TITLE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
40- SLUG=$(echo "$CLEAN_TITLE" \
41- | tr '[:upper:]' '[:lower:]' \
42- | sed 's/[[:punct:]]//g' \
43- | tr ' ' '-' \
44- )
45- SLUG=$(echo "$SLUG" \
46- | sed 's/-\+/-/g' \
47- | sed 's/^-//' \
48- | sed 's/-$//' \
49- )
50-
51- if [ -z "$SLUG" ]; then
52- echo "Slug is empty. Aborting."
53- exit 1
54- fi
55-
56- echo "Generated Slug: $SLUG"
57-
58- # 2. 다음 순번(Index) 결정 (동일 SLUG에 대해서만 순번 증가)
59-
60- REPO="${{ github.repository }}"
61- TARGET_PREFIX="feature/${SLUG}"
62-
63- # 원격 저장소에서 동일 슬러그로 시작하는 모든 브랜치 목록을 가져옵니다.
64- EXISTING_MATCHES=$(git ls-remote --heads origin "refs/heads/${TARGET_PREFIX}*" | awk '{print $2}' | sed 's/refs\/heads\///')
65-
66- MAX_INDEX=-1
67-
68- for BRANCH in $EXISTING_MATCHES; do
69- # 브랜치 이름의 접두사 패턴 설정
70- PREFIX_PATTERN="$TARGET_PREFIX"
71-
72- CURRENT_INDEX=""
73-
74- # 패턴 1: feature/SLUG-XX-issue (순번이 붙은 경우)
75- if echo "$BRANCH" | grep -E -q "^${PREFIX_PATTERN}-[0-9]{2}-issue$"; then
76- # sed 구분자를 #으로 변경하여 충돌 방지. XX만 추출합니다.
77- CURRENT_INDEX=$(echo "$BRANCH" | sed "s#^${PREFIX_PATTERN}-\([0-9]\{2\}\)-issue$#\1#")
78-
79- # 패턴 2: feature/SLUG-issue (순번이 없는 첫 번째 브랜치)
80- elif echo "$BRANCH" | grep -E -q "^${PREFIX_PATTERN}-issue$"; then
81- CURRENT_INDEX="00"
82- fi
83-
84- # CURRENT_INDEX가 추출되었을 경우에만 MAX_INDEX와 비교
85- if [ -n "$CURRENT_INDEX" ]; then
86- # 인덱스를 정수로 변환하여 비교합니다.
87- NUM_INDEX=$(printf "%d" "$CURRENT_INDEX")
88-
89- if [ "$NUM_INDEX" -gt "$MAX_INDEX" ]; then
90- MAX_INDEX="$NUM_INDEX"
91- fi
92- fi
93- done
94-
95- # 3. 브랜치 이름 포맷 결정
96-
97- DEFAULT_BRANCH_NAME="${TARGET_PREFIX}-issue"
98-
99- # 저장소에 이미 해당 브랜치명이 존재하는지 확인 (순번이 없는 기본 이름)
100- if git ls-remote --heads origin "$DEFAULT_BRANCH_NAME" | grep "$DEFAULT_BRANCH_NAME" > /dev/null; then
101- # 브랜치가 이미 존재하면, MAX_INDEX를 기준으로 다음 순번을 사용합니다.
102- # MAX_INDEX가 -1이면 00, 00이면 01, 01이면 02...
103- NEXT_INDEX=$((MAX_INDEX + 1))
104-
105- if [ "$NEXT_INDEX" -gt 20 ]; then
106- echo "Maximum index (20) reached for $SLUG. No branch created."
107- exit 1
108- fi
109-
110- FORMATTED_INDEX=$(printf "%02d" $NEXT_INDEX)
111- BRANCH_NAME="${TARGET_PREFIX}-${FORMATTED_INDEX}-issue"
112- echo "Conflict detected. Next Index: $FORMATTED_INDEX"
113- else
114- # 브랜치가 존재하지 않으면 순번이 없는 기본 이름을 사용합니다.
115- BRANCH_NAME="$DEFAULT_BRANCH_NAME"
116- echo "No conflict detected. Using default branch name."
117- fi
118-
119- echo "Final Branch Name: $BRANCH_NAME"
120-
121- # 4. 브랜치 생성 및 이슈 연결 (GH CLI 사용)
122-
123- gh issue develop "$ISSUE_NUMBER" \
124- --repo "$REPO" \
125- --branch-repo "$REPO" \
126- --base "$BASE_BRANCH" \
127- --name "$BRANCH_NAME"
128-
129- echo "Branch created and linked successfully."
130- echo "Linked branches now:"
1+ name : Create branches from issue
2+
3+ on :
4+ issues :
5+ types : [opened]
6+
7+ permissions :
8+ contents : write
9+ issues : write
10+
11+ jobs :
12+ create_branches :
13+ runs-on : ubuntu-latest
14+
15+ steps :
16+ - name : Checkout repository
17+ uses : actions/checkout@v4
18+ with :
19+ fetch-depth : 0
20+ ref : dev # 베이스 브랜치
21+
22+ - name : Install Git LFS (for stable git ls-remote)
23+ run : |
24+ sudo apt-get install git-lfs -y
25+
26+ - name : Create feature branch with sequential index if title conflicts
27+ env :
28+ ISSUE_TITLE : ${{ github.event.issue.title }}
29+ ISSUE_NUMBER : ${{ github.event.issue.number }}
30+ BASE_BRANCH : dev
31+ GH_TOKEN : ${{ github.token }}
32+ run : |
33+ set -euo pipefail
34+
35+ echo "Issue title: $ISSUE_TITLE"
36+
37+ # 1. 태그 제거 및 슬러그 생성
38+ CLEAN_TITLE=$(echo "$ISSUE_TITLE" | sed 's/^\[[^]]*\][[:space:]]*//')
39+ CLEAN_TITLE=$(echo "$CLEAN_TITLE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
40+ SLUG=$(echo "$CLEAN_TITLE" \
41+ | tr '[:upper:]' '[:lower:]' \
42+ | sed 's/[[:punct:]]//g' \
43+ | tr ' ' '-' \
44+ )
45+ SLUG=$(echo "$SLUG" \
46+ | sed 's/-\+/-/g' \
47+ | sed 's/^-//' \
48+ | sed 's/-$//' \
49+ )
50+
51+ if [ -z "$SLUG" ]; then
52+ echo "Slug is empty. Aborting."
53+ exit 1
54+ fi
55+
56+ echo "Generated Slug: $SLUG"
57+
58+ # 2. 다음 순번(Index) 결정 (동일 SLUG에 대해서만 순번 증가)
59+
60+ REPO="${{ github.repository }}"
61+ TARGET_PREFIX="feature/${SLUG}"
62+
63+ # 원격 저장소에서 동일 슬러그로 시작하는 모든 브랜치 목록을 가져옵니다.
64+ EXISTING_MATCHES=$(git ls-remote --heads origin "refs/heads/${TARGET_PREFIX}*" | awk '{print $2}' | sed 's/refs\/heads\///')
65+
66+ MAX_INDEX=-1
67+
68+ for BRANCH in $EXISTING_MATCHES; do
69+ # 브랜치 이름의 접두사 패턴 설정
70+ PREFIX_PATTERN="$TARGET_PREFIX"
71+
72+ CURRENT_INDEX=""
73+
74+ # 패턴 1: feature/SLUG-XX-issue (순번이 붙은 경우)
75+ if echo "$BRANCH" | grep -E -q "^${PREFIX_PATTERN}-[0-9]{2}-issue$"; then
76+ # sed 구분자를 #으로 변경하여 충돌 방지. XX만 추출합니다.
77+ CURRENT_INDEX=$(echo "$BRANCH" | sed "s#^${PREFIX_PATTERN}-\([0-9]\{2\}\)-issue$#\1#")
78+
79+ # 패턴 2: feature/SLUG-issue (순번이 없는 첫 번째 브랜치)
80+ elif echo "$BRANCH" | grep -E -q "^${PREFIX_PATTERN}-issue$"; then
81+ CURRENT_INDEX="00"
82+ fi
83+
84+ # CURRENT_INDEX가 추출되었을 경우에만 MAX_INDEX와 비교
85+ if [ -n "$CURRENT_INDEX" ]; then
86+ # 인덱스를 정수로 변환하여 비교합니다.
87+ NUM_INDEX=$(printf "%d" "$CURRENT_INDEX")
88+
89+ if [ "$NUM_INDEX" -gt "$MAX_INDEX" ]; then
90+ MAX_INDEX="$NUM_INDEX"
91+ fi
92+ fi
93+ done
94+
95+ # 3. 브랜치 이름 포맷 결정
96+
97+ DEFAULT_BRANCH_NAME="${TARGET_PREFIX}-issue"
98+
99+ # 저장소에 이미 해당 브랜치명이 존재하는지 확인 (순번이 없는 기본 이름)
100+ if git ls-remote --heads origin "$DEFAULT_BRANCH_NAME" | grep "$DEFAULT_BRANCH_NAME" > /dev/null; then
101+ # 브랜치가 이미 존재하면, MAX_INDEX를 기준으로 다음 순번을 사용합니다.
102+ # MAX_INDEX가 -1이면 00, 00이면 01, 01이면 02...
103+ NEXT_INDEX=$((MAX_INDEX + 1))
104+
105+ if [ "$NEXT_INDEX" -gt 20 ]; then
106+ echo "Maximum index (20) reached for $SLUG. No branch created."
107+ exit 1
108+ fi
109+
110+ FORMATTED_INDEX=$(printf "%02d" $NEXT_INDEX)
111+ BRANCH_NAME="${TARGET_PREFIX}-${FORMATTED_INDEX}-issue"
112+ echo "Conflict detected. Next Index: $FORMATTED_INDEX"
113+ else
114+ # 브랜치가 존재하지 않으면 순번이 없는 기본 이름을 사용합니다.
115+ BRANCH_NAME="$DEFAULT_BRANCH_NAME"
116+ echo "No conflict detected. Using default branch name."
117+ fi
118+
119+ echo "Final Branch Name: $BRANCH_NAME"
120+
121+ # 4. 브랜치 생성 및 이슈 연결 (GH CLI 사용)
122+
123+ gh issue develop "$ISSUE_NUMBER" \
124+ --repo "$REPO" \
125+ --branch-repo "$REPO" \
126+ --base "$BASE_BRANCH" \
127+ --name "$BRANCH_NAME"
128+
129+ echo "Branch created and linked successfully."
130+ echo "Linked branches now:"
131131 gh issue develop --list --repo "$REPO" "$ISSUE_NUMBER"
0 commit comments