Skip to content
Draft
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
79 changes: 79 additions & 0 deletions .github/scripts/create-headver-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/usr/bin/env bash

set -euo pipefail

TARGET="${TARGET:-${1:-}}"
CREATE_TAG="${CREATE_TAG:-true}"

case "$TARGET" in
web)
DISPLAY_NAME="Web"
HEADVER_PATH="apps/web/headver.json"
RELEASE_BRANCH="release-web"
TAG_PREFIX="web"
APP_PATH_REGEX="^(apps/web/|packages/|package\\.json|pnpm-lock\\.yaml|pnpm-workspace\\.yaml|turbo\\.json|vercel\\.json|scripts/)"
;;
admin)
DISPLAY_NAME="Admin"
HEADVER_PATH="apps/admin/headver.json"
RELEASE_BRANCH="release-admin"
TAG_PREFIX="admin"
APP_PATH_REGEX="^(apps/admin/|packages/|package\\.json|pnpm-lock\\.yaml|pnpm-workspace\\.yaml|turbo\\.json|vercel\\.json|scripts/)"
;;
university)
DISPLAY_NAME="University Web"
HEADVER_PATH="apps/university-web/headver.json"
RELEASE_BRANCH="release-university"
TAG_PREFIX="university"
APP_PATH_REGEX="^(apps/university-web/|packages/|package\\.json|pnpm-lock\\.yaml|pnpm-workspace\\.yaml|turbo\\.json|vercel\\.json|scripts/)"
;;
*)
echo "Unsupported target: $TARGET" >&2
exit 1
;;
esac

if [ ! -f "$HEADVER_PATH" ]; then
echo "$HEADVER_PATH 파일이 없습니다." >&2
exit 1
fi

HEAD=$(jq -r '.head // empty' "$HEADVER_PATH")
if ! [[ "$HEAD" =~ ^[0-9]+$ ]]; then
echo "$HEADVER_PATH의 head 값이 숫자가 아닙니다: $HEAD" >&2
exit 1
fi

YYWW="${YYWW_OVERRIDE:-$(date +"%y%V")}"
TAG_PATTERN="${TAG_PREFIX}-v${HEAD}.${YYWW}.*"
LAST_BUILD=$(git tag --list "$TAG_PATTERN" | awk -F. '{print $3}' | sort -n | tail -n 1)

if [ -z "$LAST_BUILD" ]; then
BUILD=1
else
BUILD=$((LAST_BUILD + 1))
fi

VERSION="${HEAD}.${YYWW}.${BUILD}"
TAG="${TAG_PREFIX}-v${VERSION}"

echo "Target: $TARGET"
echo "HeadVer path: $HEADVER_PATH"
echo "Computed tag: $TAG"

if [ "$CREATE_TAG" = "true" ]; then
git tag "$TAG"
git push origin "$TAG"
fi

OUTPUT_FILE="${GITHUB_OUTPUT:-/dev/stdout}"
{
echo "target=$TARGET"
echo "display_name=$DISPLAY_NAME"
echo "headver_path=$HEADVER_PATH"
echo "release_branch=$RELEASE_BRANCH"
echo "tag_prefix=$TAG_PREFIX"
echo "path_regex=$APP_PATH_REGEX"
echo "version=$VERSION"
echo "tag=$TAG"
} >> "$OUTPUT_FILE"
61 changes: 17 additions & 44 deletions .github/workflows/headver-tagging.yml
Original file line number Diff line number Diff line change
@@ -1,63 +1,36 @@
name: Generate HeadVer Tag

permissions:
contents: write

on:
workflow_call:
inputs:
target:
description: "App target to tag"
required: true
type: string
outputs:
version:
description: "Generated HeadVer version"
value: ${{ jobs.generate_tag.outputs.version }}
tag:
description: "Generated Git tag"
value: ${{ jobs.generate_tag.outputs.tag }}

jobs:
generate_tag:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.compute_version.outputs.version }}
version: ${{ steps.create_tag.outputs.version }}
tag: ${{ steps.create_tag.outputs.tag }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Compute HeadVer Tag
id: compute_version
run: |
# headver.json에서 head 버전 가져오기
if [ ! -f headver.json ]; then
echo "headver.json 파일이 없습니다. 기본 head=0을 사용합니다."
HEAD=0
else
HEAD=$(jq -r '.head' headver.json)
fi
echo "Head number: $HEAD"

# 현재 연도와 주차(yyww) 가져오기
YYWW=$(date +"%y%V")
echo "YearWeek: $YYWW"

# 최신 태그 검색
LAST_BUILD=$(git tag --list "v*.*.*" | awk -F. '{print $3}' | sort -n | tail -n 1)

if [ -z "$LAST_BUILD" ]; then
BUILD=1
else
BUILD=$((LAST_BUILD + 1))
fi

echo "Build number: $BUILD"

# 최종 태그 생성
VERSION="${HEAD}.${YYWW}.${BUILD}"
echo "Computed version: $VERSION"

# GitHub Actions 환경 변수로 설정
echo "version=$VERSION" >> $GITHUB_ENV
echo "::set-output name=version::$VERSION"

- name: Create Tag
run: |
TAG="v${{ steps.compute_version.outputs.version }}"
echo "Creating tag: $TAG"

git tag $TAG
git push origin $TAG
- name: Create app HeadVer tag
id: create_tag
env:
TARGET: ${{ inputs.target }}
run: bash .github/scripts/create-headver-tag.sh
149 changes: 95 additions & 54 deletions .github/workflows/pr-auto-label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,107 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write

issues: write
pull-requests: read

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect changed apps
id: detect
run: |
# Get changed files between base and head
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"

FILES=$(git diff --name-only $BASE_SHA $HEAD_SHA)

echo "Changed files:"
echo "$FILES"

# Check for web changes
if echo "$FILES" | grep -q "^apps/web/"; then
echo "web=true" >> $GITHUB_OUTPUT
echo "✓ Detected changes in apps/web"
else
echo "web=false" >> $GITHUB_OUTPUT
fi

# Check for admin changes
if echo "$FILES" | grep -q "^apps/admin/"; then
echo "admin=true" >> $GITHUB_OUTPUT
echo "✓ Detected changes in apps/admin"
else
echo "admin=false" >> $GITHUB_OUTPUT
fi

- name: Add labels
- name: Sync app labels
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const labels = [];

if ('${{ steps.detect.outputs.web }}' === 'true') {
labels.push('web');
const appLabels = [
{
name: 'web',
color: '1d76db',
description: 'Changes in apps/web',
pattern: /^apps\/web\//,
},
{
name: 'admin',
color: 'd73a4a',
description: 'Changes in apps/admin',
pattern: /^apps\/admin\//,
},
{
name: 'university',
color: '0e8a16',
description: 'Changes in apps/university-web',
pattern: /^apps\/university-web\//,
},
];

const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const pull_number = context.payload.pull_request.number;

const changedFiles = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number,
per_page: 100,
});
const filenames = changedFiles.map((file) => file.filename);

console.log('Changed files:');
console.log(filenames.join('\n'));

const labelsToAdd = appLabels
.filter((label) => filenames.some((filename) => label.pattern.test(filename)))
.map((label) => label.name);

const managedLabelNames = new Set(appLabels.map((label) => label.name));
const currentLabels = await github.paginate(github.rest.issues.listLabelsOnIssue, {
owner,
repo,
issue_number,
per_page: 100,
});

for (const label of currentLabels) {
if (!managedLabelNames.has(label.name) || labelsToAdd.includes(label.name)) {
continue;
}

console.log(`Removing stale label: ${label.name}`);
await github.rest.issues.removeLabel({
owner,
repo,
issue_number,
name: label.name,
});
}

if ('${{ steps.detect.outputs.admin }}' === 'true') {
labels.push('admin');

for (const labelName of labelsToAdd) {
const label = appLabels.find((item) => item.name === labelName);

try {
await github.rest.issues.getLabel({ owner, repo, name: label.name });
} catch (error) {
if (error.status !== 404) {
throw error;
}

console.log(`Creating missing label: ${label.name}`);
await github.rest.issues.createLabel({
owner,
repo,
name: label.name,
color: label.color,
description: label.description,
});
}
}

if (labels.length > 0) {
console.log(`Adding labels: ${labels.join(', ')}`);

await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: labels
});
} else {

if (labelsToAdd.length === 0) {
console.log('No app-specific changes detected');
return;
}

console.log(`Adding labels: ${labelsToAdd.join(', ')}`);
await github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels: labelsToAdd,
});
Loading
Loading