tylersong 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/actions/discord-notify/action.yml +119 -0
- package/.github/actions/setup-runtime/action.yml +41 -0
- package/.github/workflows/ci.yml +176 -0
- package/.github/workflows/publish.yml +232 -0
- package/README.md +47 -0
- package/bun.lock +146 -0
- package/bunfig.toml +16 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/docs/deployment.md +82 -0
- package/docs/discord-setup.md +158 -0
- package/docs/github-actions-fixes.md +142 -0
- package/docs/usage.md +112 -0
- package/docs/workflows.md +176 -0
- package/package.json +24 -4
- package/{index.js → src/index.ts} +38 -3
- package/tsconfig.json +20 -0
- package/.github/workflows/npm-publish.yml +0 -48
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: "Discord Notification"
|
|
2
|
+
description: "Send notification to Discord webhook"
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
webhook-url:
|
|
6
|
+
description: "Discord webhook URL"
|
|
7
|
+
required: true
|
|
8
|
+
status:
|
|
9
|
+
description: "Status of the workflow (success, failure, cancelled)"
|
|
10
|
+
required: true
|
|
11
|
+
title:
|
|
12
|
+
description: "Notification title"
|
|
13
|
+
required: true
|
|
14
|
+
description:
|
|
15
|
+
description: "Notification description"
|
|
16
|
+
required: false
|
|
17
|
+
default: ""
|
|
18
|
+
color:
|
|
19
|
+
description: "Embed color (hex without #)"
|
|
20
|
+
required: false
|
|
21
|
+
default: "5865F2"
|
|
22
|
+
fields:
|
|
23
|
+
description: "Additional fields in JSON format"
|
|
24
|
+
required: false
|
|
25
|
+
default: "[]"
|
|
26
|
+
|
|
27
|
+
runs:
|
|
28
|
+
using: "composite"
|
|
29
|
+
steps:
|
|
30
|
+
- name: Set color based on status
|
|
31
|
+
shell: bash
|
|
32
|
+
id: color
|
|
33
|
+
run: |
|
|
34
|
+
case "${{ inputs.status }}" in
|
|
35
|
+
success)
|
|
36
|
+
echo "color=00FF00" >> $GITHUB_OUTPUT
|
|
37
|
+
echo "emoji=✅" >> $GITHUB_OUTPUT
|
|
38
|
+
;;
|
|
39
|
+
failure)
|
|
40
|
+
echo "color=FF0000" >> $GITHUB_OUTPUT
|
|
41
|
+
echo "emoji=❌" >> $GITHUB_OUTPUT
|
|
42
|
+
;;
|
|
43
|
+
cancelled)
|
|
44
|
+
echo "color=FFA500" >> $GITHUB_OUTPUT
|
|
45
|
+
echo "emoji=⚠️" >> $GITHUB_OUTPUT
|
|
46
|
+
;;
|
|
47
|
+
*)
|
|
48
|
+
echo "color=${{ inputs.color }}" >> $GITHUB_OUTPUT
|
|
49
|
+
echo "emoji=ℹ️" >> $GITHUB_OUTPUT
|
|
50
|
+
;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
- name: Send Discord notification
|
|
54
|
+
shell: bash
|
|
55
|
+
env:
|
|
56
|
+
WEBHOOK_URL: ${{ inputs.webhook-url }}
|
|
57
|
+
STATUS: ${{ inputs.status }}
|
|
58
|
+
TITLE: ${{ inputs.title }}
|
|
59
|
+
DESCRIPTION: ${{ inputs.description }}
|
|
60
|
+
COLOR: ${{ steps.color.outputs.color }}
|
|
61
|
+
EMOJI: ${{ steps.color.outputs.emoji }}
|
|
62
|
+
FIELDS: ${{ inputs.fields }}
|
|
63
|
+
run: |
|
|
64
|
+
# 16진수 색상을 10진수로 변환
|
|
65
|
+
COLOR_DEC=$((16#$COLOR))
|
|
66
|
+
|
|
67
|
+
# 안전한 JSON 페이로드 생성 (임시 파일 사용)
|
|
68
|
+
TEMP_FILE=$(mktemp)
|
|
69
|
+
|
|
70
|
+
# 기본 구조 생성
|
|
71
|
+
jq -n \
|
|
72
|
+
--arg emoji "$EMOJI" \
|
|
73
|
+
--arg title "$TITLE" \
|
|
74
|
+
--arg description "$DESCRIPTION" \
|
|
75
|
+
--argjson color "$COLOR_DEC" \
|
|
76
|
+
'{
|
|
77
|
+
embeds: [{
|
|
78
|
+
title: ($emoji + " " + $title),
|
|
79
|
+
description: $description,
|
|
80
|
+
color: $color,
|
|
81
|
+
footer: {
|
|
82
|
+
text: "GitHub Actions",
|
|
83
|
+
icon_url: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
|
84
|
+
},
|
|
85
|
+
timestamp: (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))
|
|
86
|
+
}]
|
|
87
|
+
}' > "$TEMP_FILE"
|
|
88
|
+
|
|
89
|
+
# fields가 비어있지 않으면 추가
|
|
90
|
+
if [ "$FIELDS" != "[]" ] && [ -n "$FIELDS" ]; then
|
|
91
|
+
jq --argjson fields "$FIELDS" '.embeds[0].fields = $fields' "$TEMP_FILE" > "${TEMP_FILE}.tmp" && mv "${TEMP_FILE}.tmp" "$TEMP_FILE"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Discord 웹훅으로 전송 (디버그 정보 포함)
|
|
95
|
+
echo "Sending payload:"
|
|
96
|
+
cat "$TEMP_FILE"
|
|
97
|
+
echo ""
|
|
98
|
+
|
|
99
|
+
RESPONSE=$(curl -s -w "%{http_code}" -H "Content-Type: application/json" \
|
|
100
|
+
-d @"$TEMP_FILE" \
|
|
101
|
+
"$WEBHOOK_URL")
|
|
102
|
+
|
|
103
|
+
HTTP_CODE="${RESPONSE: -3}"
|
|
104
|
+
RESPONSE_BODY="${RESPONSE%???}"
|
|
105
|
+
|
|
106
|
+
echo "HTTP Status: $HTTP_CODE"
|
|
107
|
+
echo "Response: $RESPONSE_BODY"
|
|
108
|
+
|
|
109
|
+
# 임시 파일 정리
|
|
110
|
+
rm -f "$TEMP_FILE"
|
|
111
|
+
|
|
112
|
+
# 상태 코드 확인
|
|
113
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
114
|
+
echo "✅ Discord 알림 전송 성공"
|
|
115
|
+
else
|
|
116
|
+
echo "❌ Discord 알림 전송 실패: HTTP $HTTP_CODE"
|
|
117
|
+
echo "Response: $RESPONSE_BODY"
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: "Setup Runtime Environment"
|
|
2
|
+
description: "Setup Node.js or Bun runtime with dependencies"
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
runtime:
|
|
6
|
+
description: "Runtime to setup (node or bun)"
|
|
7
|
+
required: true
|
|
8
|
+
node-version:
|
|
9
|
+
description: "Node.js version"
|
|
10
|
+
required: false
|
|
11
|
+
default: "20.x"
|
|
12
|
+
bun-version:
|
|
13
|
+
description: "Bun version"
|
|
14
|
+
required: false
|
|
15
|
+
default: "latest"
|
|
16
|
+
|
|
17
|
+
runs:
|
|
18
|
+
using: "composite"
|
|
19
|
+
steps:
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
if: inputs.runtime == 'node'
|
|
22
|
+
uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: ${{ inputs.node-version }}
|
|
25
|
+
cache: "npm"
|
|
26
|
+
|
|
27
|
+
- name: Setup Bun
|
|
28
|
+
if: inputs.runtime == 'bun'
|
|
29
|
+
uses: oven-sh/setup-bun@v1
|
|
30
|
+
with:
|
|
31
|
+
bun-version: ${{ inputs.bun-version }}
|
|
32
|
+
|
|
33
|
+
- name: Install dependencies (Node.js)
|
|
34
|
+
if: inputs.runtime == 'node'
|
|
35
|
+
shell: bash
|
|
36
|
+
run: npm ci
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies (Bun)
|
|
39
|
+
if: inputs.runtime == 'bun'
|
|
40
|
+
shell: bash
|
|
41
|
+
run: bun install
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
name: Continuous Integration
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
runtime: [node, bun]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout code
|
|
20
|
+
uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Setup runtime environment
|
|
23
|
+
uses: ./.github/actions/setup-runtime
|
|
24
|
+
with:
|
|
25
|
+
runtime: ${{ matrix.runtime }}
|
|
26
|
+
|
|
27
|
+
- name: Run tests (Node.js)
|
|
28
|
+
if: matrix.runtime == 'node'
|
|
29
|
+
run: npm test
|
|
30
|
+
|
|
31
|
+
- name: Run tests (Bun)
|
|
32
|
+
if: matrix.runtime == 'bun'
|
|
33
|
+
run: bun test || echo "No bun tests specified"
|
|
34
|
+
|
|
35
|
+
- name: Test CLI functionality (Node.js)
|
|
36
|
+
if: matrix.runtime == 'node'
|
|
37
|
+
run: |
|
|
38
|
+
npm run build
|
|
39
|
+
node dist/index.js --version
|
|
40
|
+
node dist/index.js --help
|
|
41
|
+
|
|
42
|
+
- name: Test CLI functionality (Bun)
|
|
43
|
+
if: matrix.runtime == 'bun'
|
|
44
|
+
run: |
|
|
45
|
+
bun run build:bun
|
|
46
|
+
bun run dist/index.js --version
|
|
47
|
+
bun run dist/index.js --help
|
|
48
|
+
|
|
49
|
+
build:
|
|
50
|
+
name: Build & Upload Artifacts
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
needs: test
|
|
53
|
+
|
|
54
|
+
steps:
|
|
55
|
+
- name: Checkout code
|
|
56
|
+
uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Setup Node.js environment
|
|
59
|
+
uses: ./.github/actions/setup-runtime
|
|
60
|
+
with:
|
|
61
|
+
runtime: node
|
|
62
|
+
|
|
63
|
+
- name: Build TypeScript
|
|
64
|
+
run: npm run build
|
|
65
|
+
|
|
66
|
+
- name: Upload build artifacts
|
|
67
|
+
uses: actions/upload-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: dist-files-${{ github.sha }}
|
|
70
|
+
path: dist/
|
|
71
|
+
retention-days: 30
|
|
72
|
+
|
|
73
|
+
- name: Upload type definitions
|
|
74
|
+
uses: actions/upload-artifact@v4
|
|
75
|
+
with:
|
|
76
|
+
name: types-${{ github.sha }}
|
|
77
|
+
path: |
|
|
78
|
+
dist/*.d.ts
|
|
79
|
+
dist/*.d.ts.map
|
|
80
|
+
retention-days: 30
|
|
81
|
+
|
|
82
|
+
lint:
|
|
83
|
+
name: Code Quality
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
|
|
86
|
+
steps:
|
|
87
|
+
- name: Checkout code
|
|
88
|
+
uses: actions/checkout@v4
|
|
89
|
+
|
|
90
|
+
- name: Setup Node.js environment
|
|
91
|
+
uses: ./.github/actions/setup-runtime
|
|
92
|
+
with:
|
|
93
|
+
runtime: node
|
|
94
|
+
|
|
95
|
+
- name: Check TypeScript compilation
|
|
96
|
+
run: npx tsc --noEmit
|
|
97
|
+
|
|
98
|
+
- name: Check code formatting (if prettier is added)
|
|
99
|
+
run: echo "Add prettier check here if needed"
|
|
100
|
+
|
|
101
|
+
- name: Security audit
|
|
102
|
+
run: npm audit --audit-level=moderate
|
|
103
|
+
|
|
104
|
+
notify:
|
|
105
|
+
name: Notify Results
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
needs: [test, build, lint]
|
|
108
|
+
if: always()
|
|
109
|
+
|
|
110
|
+
steps:
|
|
111
|
+
- name: Checkout code
|
|
112
|
+
uses: actions/checkout@v4
|
|
113
|
+
|
|
114
|
+
- name: Determine overall status
|
|
115
|
+
id: status
|
|
116
|
+
run: |
|
|
117
|
+
if [ "${{ needs.test.result }}" == "success" ] && [ "${{ needs.build.result }}" == "success" ] && [ "${{ needs.lint.result }}" == "success" ]; then
|
|
118
|
+
echo "status=success" >> $GITHUB_OUTPUT
|
|
119
|
+
echo "title=CI 성공 🎉" >> $GITHUB_OUTPUT
|
|
120
|
+
echo "description=모든 테스트, 빌드, 린팅이 성공적으로 완료되었습니다." >> $GITHUB_OUTPUT
|
|
121
|
+
else
|
|
122
|
+
echo "status=failure" >> $GITHUB_OUTPUT
|
|
123
|
+
echo "title=CI 실패 💥" >> $GITHUB_OUTPUT
|
|
124
|
+
echo "description=CI 파이프라인에서 오류가 발생했습니다. 로그를 확인해주세요." >> $GITHUB_OUTPUT
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
- name: Create fields JSON
|
|
128
|
+
id: fields
|
|
129
|
+
run: |
|
|
130
|
+
FIELDS=$(cat << EOF
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
"name": "브랜치",
|
|
134
|
+
"value": "${{ github.ref_name }}",
|
|
135
|
+
"inline": true
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "커밋",
|
|
139
|
+
"value": "[\`${GITHUB_SHA:0:7}\`](https://github.com/${{ github.repository }}/commit/${{ github.sha }})",
|
|
140
|
+
"inline": true
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "테스트",
|
|
144
|
+
"value": "${{ needs.test.result == 'success' && '✅ 성공' || '❌ 실패' }}",
|
|
145
|
+
"inline": true
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "빌드",
|
|
149
|
+
"value": "${{ needs.build.result == 'success' && '✅ 성공' || '❌ 실패' }}",
|
|
150
|
+
"inline": true
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "린팅",
|
|
154
|
+
"value": "${{ needs.lint.result == 'success' && '✅ 성공' || '❌ 실패' }}",
|
|
155
|
+
"inline": true
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "작업자",
|
|
159
|
+
"value": "${{ github.actor }}",
|
|
160
|
+
"inline": true
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
EOF
|
|
164
|
+
)
|
|
165
|
+
echo "fields<<EOF" >> $GITHUB_OUTPUT
|
|
166
|
+
echo "$FIELDS" >> $GITHUB_OUTPUT
|
|
167
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
168
|
+
|
|
169
|
+
- name: Send Discord notification
|
|
170
|
+
uses: ./.github/actions/discord-notify
|
|
171
|
+
with:
|
|
172
|
+
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
173
|
+
status: ${{ steps.status.outputs.status }}
|
|
174
|
+
title: ${{ steps.status.outputs.title }}
|
|
175
|
+
description: ${{ steps.status.outputs.description }}
|
|
176
|
+
fields: ${{ steps.fields.outputs.fields }}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
name: Publish to NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
workflow_run:
|
|
8
|
+
workflows: ["Continuous Integration"]
|
|
9
|
+
types: [completed]
|
|
10
|
+
branches: [main]
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
check-ci:
|
|
14
|
+
name: Check CI Status
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
if: always()
|
|
17
|
+
outputs:
|
|
18
|
+
ci-success: ${{ steps.ci-check.outputs.success }}
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check CI workflow status
|
|
22
|
+
id: ci-check
|
|
23
|
+
run: |
|
|
24
|
+
if [ "${{ github.event_name }}" == "workflow_run" ]; then
|
|
25
|
+
if [ "${{ github.event.workflow_run.conclusion }}" == "success" ]; then
|
|
26
|
+
echo "success=true" >> $GITHUB_OUTPUT
|
|
27
|
+
else
|
|
28
|
+
echo "success=false" >> $GITHUB_OUTPUT
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
else
|
|
32
|
+
# For push and tag events, assume CI will run or has run
|
|
33
|
+
echo "success=true" >> $GITHUB_OUTPUT
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
version-check:
|
|
37
|
+
name: Check Version Changes
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
if: |
|
|
40
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
41
|
+
startsWith(github.ref, 'refs/tags/v') ||
|
|
42
|
+
(github.event_name == 'workflow_run' && needs.check-ci.outputs.ci-success == 'true')
|
|
43
|
+
needs:
|
|
44
|
+
- check-ci
|
|
45
|
+
outputs:
|
|
46
|
+
should-publish: ${{ steps.version-check.outputs.should-publish }}
|
|
47
|
+
current-version: ${{ steps.version-check.outputs.current-version }}
|
|
48
|
+
|
|
49
|
+
steps:
|
|
50
|
+
- name: Checkout code
|
|
51
|
+
uses: actions/checkout@v4
|
|
52
|
+
|
|
53
|
+
- name: Setup Node.js environment
|
|
54
|
+
uses: ./.github/actions/setup-runtime
|
|
55
|
+
with:
|
|
56
|
+
runtime: node
|
|
57
|
+
|
|
58
|
+
- name: Check version changes
|
|
59
|
+
id: version-check
|
|
60
|
+
run: |
|
|
61
|
+
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
62
|
+
PUBLISHED_VERSION=$(npm view tylersong version 2>/dev/null || echo "0.0.0")
|
|
63
|
+
|
|
64
|
+
echo "current-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
65
|
+
echo "Current version: $CURRENT_VERSION"
|
|
66
|
+
echo "Published version: $PUBLISHED_VERSION"
|
|
67
|
+
|
|
68
|
+
# Tag push는 항상 배포
|
|
69
|
+
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
|
|
70
|
+
echo "should-publish=true" >> $GITHUB_OUTPUT
|
|
71
|
+
echo "Tag push detected: will publish"
|
|
72
|
+
# main 브랜치는 버전이 다를 때만 배포
|
|
73
|
+
elif [ "$CURRENT_VERSION" != "$PUBLISHED_VERSION" ]; then
|
|
74
|
+
echo "should-publish=true" >> $GITHUB_OUTPUT
|
|
75
|
+
echo "Version changed: will publish"
|
|
76
|
+
else
|
|
77
|
+
echo "should-publish=false" >> $GITHUB_OUTPUT
|
|
78
|
+
echo "Version unchanged: skipping publish"
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
publish:
|
|
82
|
+
name: Publish Package
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
needs: [version-check]
|
|
85
|
+
if: needs.version-check.outputs.should-publish == 'true'
|
|
86
|
+
|
|
87
|
+
steps:
|
|
88
|
+
- name: Checkout code
|
|
89
|
+
uses: actions/checkout@v4
|
|
90
|
+
|
|
91
|
+
- name: Setup Node.js for publishing
|
|
92
|
+
uses: actions/setup-node@v4
|
|
93
|
+
with:
|
|
94
|
+
node-version: "20.x"
|
|
95
|
+
registry-url: "https://registry.npmjs.org/"
|
|
96
|
+
cache: "npm"
|
|
97
|
+
|
|
98
|
+
- name: Install dependencies
|
|
99
|
+
run: npm ci
|
|
100
|
+
|
|
101
|
+
- name: Build for publishing
|
|
102
|
+
run: npm run build
|
|
103
|
+
|
|
104
|
+
- name: Verify build artifacts
|
|
105
|
+
run: |
|
|
106
|
+
ls -la dist/
|
|
107
|
+
test -f dist/index.js || (echo "Build artifact missing!" && exit 1)
|
|
108
|
+
|
|
109
|
+
- name: Publish to NPM (Dry Run)
|
|
110
|
+
if: github.event_name == 'pull_request'
|
|
111
|
+
run: npm publish --dry-run
|
|
112
|
+
env:
|
|
113
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
114
|
+
|
|
115
|
+
- name: Publish to NPM
|
|
116
|
+
if: github.event_name != 'pull_request'
|
|
117
|
+
run: npm publish
|
|
118
|
+
env:
|
|
119
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
120
|
+
|
|
121
|
+
- name: Create GitHub Release
|
|
122
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
123
|
+
uses: actions/github-script@v7
|
|
124
|
+
with:
|
|
125
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
126
|
+
script: |
|
|
127
|
+
const { owner, repo } = context.repo;
|
|
128
|
+
const tagName = context.ref.replace('refs/tags/', '');
|
|
129
|
+
const version = '${{ needs.version-check.outputs.current-version }}';
|
|
130
|
+
|
|
131
|
+
await github.rest.repos.createRelease({
|
|
132
|
+
owner,
|
|
133
|
+
repo,
|
|
134
|
+
tag_name: tagName,
|
|
135
|
+
name: `Release v${version}`,
|
|
136
|
+
body: `🚀 **tylersong CLI v${version}**
|
|
137
|
+
|
|
138
|
+
### 설치
|
|
139
|
+
\`\`\`bash
|
|
140
|
+
npx tylersong
|
|
141
|
+
\`\`\`
|
|
142
|
+
|
|
143
|
+
### 변경사항
|
|
144
|
+
이 릴리스의 전체 변경사항은 [커밋 히스토리](https://github.com/${owner}/${repo}/commits/v${version})를 확인해주세요.`,
|
|
145
|
+
draft: false,
|
|
146
|
+
prerelease: false
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
notify:
|
|
150
|
+
name: Notification
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
needs: [publish, version-check]
|
|
153
|
+
if: always() && needs.version-check.outputs.should-publish == 'true'
|
|
154
|
+
|
|
155
|
+
steps:
|
|
156
|
+
- name: Checkout code
|
|
157
|
+
uses: actions/checkout@v4
|
|
158
|
+
|
|
159
|
+
- name: Determine publish status
|
|
160
|
+
id: status
|
|
161
|
+
run: |
|
|
162
|
+
if [ "${{ needs.publish.result }}" == "success" ]; then
|
|
163
|
+
echo "status=success" >> $GITHUB_OUTPUT
|
|
164
|
+
echo "title=패키지 배포 성공 🚀" >> $GITHUB_OUTPUT
|
|
165
|
+
echo "description=tylersong v${{ needs.version-check.outputs.current-version }}이 NPM에 성공적으로 배포되었습니다!" >> $GITHUB_OUTPUT
|
|
166
|
+
else
|
|
167
|
+
echo "status=failure" >> $GITHUB_OUTPUT
|
|
168
|
+
echo "title=패키지 배포 실패 💥" >> $GITHUB_OUTPUT
|
|
169
|
+
echo "description=tylersong v${{ needs.version-check.outputs.current-version }} 배포 중 오류가 발생했습니다." >> $GITHUB_OUTPUT
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
- name: Create fields JSON
|
|
173
|
+
id: fields
|
|
174
|
+
run: |
|
|
175
|
+
RELEASE_TYPE="${{ startsWith(github.ref, 'refs/tags/v') && 'Tag Release' || 'Auto Deploy' }}"
|
|
176
|
+
FIELDS=$(cat << EOF
|
|
177
|
+
[
|
|
178
|
+
{
|
|
179
|
+
"name": "버전",
|
|
180
|
+
"value": "v${{ needs.version-check.outputs.current-version }}",
|
|
181
|
+
"inline": true
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "배포 타입",
|
|
185
|
+
"value": "$RELEASE_TYPE",
|
|
186
|
+
"inline": true
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"name": "브랜치/태그",
|
|
190
|
+
"value": "${{ github.ref_name }}",
|
|
191
|
+
"inline": true
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"name": "NPM",
|
|
195
|
+
"value": "[tylersong 패키지](https://www.npmjs.com/package/tylersong)",
|
|
196
|
+
"inline": false
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"name": "설치 명령어",
|
|
200
|
+
"value": "\`npx tylersong\`",
|
|
201
|
+
"inline": false
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "배포자",
|
|
205
|
+
"value": "${{ github.actor }}",
|
|
206
|
+
"inline": true
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
EOF
|
|
210
|
+
)
|
|
211
|
+
echo "fields<<EOF" >> $GITHUB_OUTPUT
|
|
212
|
+
echo "$FIELDS" >> $GITHUB_OUTPUT
|
|
213
|
+
echo "EOF" >> $GITHUB_OUTPUT
|
|
214
|
+
|
|
215
|
+
- name: Send Discord notification
|
|
216
|
+
uses: ./.github/actions/discord-notify
|
|
217
|
+
with:
|
|
218
|
+
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
219
|
+
status: ${{ steps.status.outputs.status }}
|
|
220
|
+
title: ${{ steps.status.outputs.title }}
|
|
221
|
+
description: ${{ steps.status.outputs.description }}
|
|
222
|
+
fields: ${{ steps.fields.outputs.fields }}
|
|
223
|
+
|
|
224
|
+
- name: Console output
|
|
225
|
+
run: |
|
|
226
|
+
if [ "${{ needs.publish.result }}" == "success" ]; then
|
|
227
|
+
echo "✅ Package v${{ needs.version-check.outputs.current-version }} published successfully!"
|
|
228
|
+
echo "📦 NPM: https://www.npmjs.com/package/tylersong"
|
|
229
|
+
else
|
|
230
|
+
echo "❌ Package publish failed!"
|
|
231
|
+
exit 1
|
|
232
|
+
fi
|
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# tylersong CLI
|
|
2
|
+
|
|
3
|
+
## 개요
|
|
4
|
+
|
|
5
|
+
송민성의 개발자 프로필을 터미널에서 확인할 수 있는 TypeScript CLI 도구입니다.
|
|
6
|
+
|
|
7
|
+
## 빠른 시작
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx tylersong
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 문서
|
|
14
|
+
|
|
15
|
+
- **사용법**: [docs/usage.md](./docs/usage.md)
|
|
16
|
+
- **배포 가이드**: [docs/deployment.md](./docs/deployment.md)
|
|
17
|
+
- **워크플로우**: [docs/workflows.md](./docs/workflows.md)
|
|
18
|
+
- **Discord 알림**: [docs/discord-setup.md](./docs/discord-setup.md)
|
|
19
|
+
- **GitHub Actions 수정사항**: [docs/github-actions-fixes.md](./docs/github-actions-fixes.md)
|
|
20
|
+
|
|
21
|
+
## 개발
|
|
22
|
+
|
|
23
|
+
### NPM 사용
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
npm run dev
|
|
28
|
+
npm run build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Bun 사용 (더 빠른 성능!)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun install
|
|
35
|
+
bun run dev:bun # TypeScript 직접 실행
|
|
36
|
+
bun run build:bun # bun 번들러로 빌드
|
|
37
|
+
bun run src/index.ts # 소스 직접 실행
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 버전 업데이트
|
|
41
|
+
|
|
42
|
+
1. 버전 업데이트: `npm version patch` (또는 minor/major)
|
|
43
|
+
2. 태그와 함께 GitHub에 푸시: `git push origin main --tags`
|
|
44
|
+
|
|
45
|
+
## 라이센스
|
|
46
|
+
|
|
47
|
+
MIT
|