Skip to content

Commit d418415

Browse files
committed
2 parents 78d8c43 + aa4c6e2 commit d418415

File tree

5 files changed

+275
-26
lines changed

5 files changed

+275
-26
lines changed

.github/workflows/calculate-score.yml

Lines changed: 145 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ on:
77
push:
88
branches:
99
- main
10+
pull_request:
11+
types: [opened, synchronize, reopened]
12+
branches:
13+
- main
1014

1115
jobs:
1216
calculate-score:
@@ -23,23 +27,36 @@ jobs:
2327
- name: Check for student's article
2428
id: check_article
2529
run: |
26-
REPO_NAME=${{ github.repository }}
27-
OWNER=$(echo $REPO_NAME | cut -d'/' -f1)
28-
REPO=$(echo $REPO_NAME | cut -d'/' -f2)
30+
# 确定要检测的仓库和学员用户名
31+
if [ "${{ github.event_name }}" = "pull_request" ]; then
32+
# PR 事件:检测 PR 来源仓库(学员 Fork 的仓库)
33+
CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }}
34+
CHECK_REPO=${{ github.event.pull_request.head.repo.name }}
35+
STUDENT_NAME=${{ github.actor }}
36+
echo "PR 模式:检测仓库 $CHECK_OWNER/$CHECK_REPO,学员 $STUDENT_NAME"
37+
else
38+
# 非 PR 事件:检测当前仓库
39+
REPO_NAME=${{ github.repository }}
40+
CHECK_OWNER=$(echo $REPO_NAME | cut -d'/' -f1)
41+
CHECK_REPO=$(echo $REPO_NAME | cut -d'/' -f2)
42+
STUDENT_NAME=$CHECK_OWNER
43+
echo "非 PR 模式:检测仓库 $CHECK_OWNER/$CHECK_REPO,学员 $STUDENT_NAME"
44+
fi
2945
3046
ARTICLE_EXISTS=0
3147
3248
CONTENTS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
33-
"https://api.github.com/repos/$OWNER/$REPO/contents")
49+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents")
3450
35-
if echo "$CONTENTS_RESPONSE" | jq -r '.[].name' | grep -q "^$OWNER\.md$"; then
51+
if echo "$CONTENTS_RESPONSE" | jq -r '.[].name' | grep -q "^$STUDENT_NAME\.md$"; then
3652
ARTICLE_EXISTS=1
37-
echo "Found article file: $OWNER.md"
53+
echo "Found article file: $STUDENT_NAME.md"
3854
else
39-
echo "No article file named $OWNER.md found"
55+
echo "No article file named $STUDENT_NAME.md found"
4056
fi
4157
4258
echo "article_exists=$ARTICLE_EXISTS" >> $GITHUB_ENV
59+
echo "student_name=$STUDENT_NAME" >> $GITHUB_ENV
4360
4461
if [ $ARTICLE_EXISTS -eq 1 ]; then
4562
ARTICLE_BONUS=20
@@ -48,64 +65,134 @@ jobs:
4865
fi
4966
echo "article_bonus=$ARTICLE_BONUS" >> $GITHUB_ENV
5067
68+
- name: Check for lesson assignments
69+
id: check_lessons
70+
if: github.event_name == 'pull_request'
71+
run: |
72+
# PR 事件:检测 PR 来源仓库(学员 Fork 的仓库)
73+
CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }}
74+
CHECK_REPO=${{ github.event.pull_request.head.repo.name }}
75+
STUDENT_NAME=${{ github.actor }}
76+
77+
echo "检测学员 $STUDENT_NAME 在仓库 $CHECK_OWNER/$CHECK_REPO 中的作业"
78+
79+
LESSON1_EXISTS=0
80+
LESSON2_EXISTS=0
81+
82+
# Check lesson1 assignment
83+
LESSON1_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
84+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents/assignments/lesson1")
85+
86+
if echo "$LESSON1_RESPONSE" | jq -r '.[].name' 2>/dev/null | grep -q "^$STUDENT_NAME\.md$"; then
87+
LESSON1_EXISTS=1
88+
echo "Found lesson1 assignment: assignments/lesson1/$STUDENT_NAME.md"
89+
else
90+
echo "No lesson1 assignment found for $STUDENT_NAME"
91+
fi
92+
93+
# Check lesson2 assignment
94+
LESSON2_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
95+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/contents/assignments/lesson2")
96+
97+
if echo "$LESSON2_RESPONSE" | jq -r '.[].name' 2>/dev/null | grep -q "^$STUDENT_NAME\.md$"; then
98+
LESSON2_EXISTS=1
99+
echo "Found lesson2 assignment: assignments/lesson2/$STUDENT_NAME.md"
100+
else
101+
echo "No lesson2 assignment found for $STUDENT_NAME"
102+
fi
103+
104+
echo "lesson1_exists=$LESSON1_EXISTS" >> $GITHUB_ENV
105+
echo "lesson2_exists=$LESSON2_EXISTS" >> $GITHUB_ENV
106+
107+
if [ $LESSON1_EXISTS -eq 1 ]; then
108+
LESSON1_SCORE=10
109+
else
110+
LESSON1_SCORE=0
111+
fi
112+
113+
if [ $LESSON2_EXISTS -eq 1 ]; then
114+
LESSON2_SCORE=10
115+
else
116+
LESSON2_SCORE=0
117+
fi
118+
119+
echo "lesson1_score=$LESSON1_SCORE" >> $GITHUB_ENV
120+
echo "lesson2_score=$LESSON2_SCORE" >> $GITHUB_ENV
121+
51122
- name: Calculate score based on GitHub metrics
52123
id: calculate
53124
run: |
54-
REPO_NAME=${{ github.repository }}
55-
OWNER=$(echo $REPO_NAME | cut -d'/' -f1)
56-
REPO=$(echo $REPO_NAME | cut -d'/' -f2)
125+
# 确定要统计的仓库
126+
if [ "${{ github.event_name }}" = "pull_request" ]; then
127+
# PR 事件:统计 PR 来源仓库(学员 Fork 的仓库)的数据
128+
CHECK_OWNER=${{ github.event.pull_request.head.repo.owner.login }}
129+
CHECK_REPO=${{ github.event.pull_request.head.repo.name }}
130+
STUDENT_NAME=${{ github.actor }}
131+
else
132+
# 非 PR 事件:统计当前仓库
133+
REPO_NAME=${{ github.repository }}
134+
CHECK_OWNER=$(echo $REPO_NAME | cut -d'/' -f1)
135+
CHECK_REPO=$(echo $REPO_NAME | cut -d'/' -f2)
136+
STUDENT_NAME=$CHECK_OWNER
137+
fi
57138
58-
echo "Repository: $OWNER/$REPO"
139+
echo "Repository: $CHECK_OWNER/$CHECK_REPO"
140+
echo "Student: $STUDENT_NAME"
59141
60142
STARS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
61-
"https://api.github.com/repos/$OWNER/$REPO")
143+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO")
62144
STARS=$(echo $STARS_RESPONSE | jq -r '.stargazers_count // 0')
63145
echo "Stars response: $STARS_RESPONSE"
64146
65147
ALL_ISSUES_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
66-
"https://api.github.com/repos/$OWNER/$REPO/issues?state=all&per_page=100")
148+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/issues?state=all&per_page=100")
67149
ALL_ISSUES=$(echo "$ALL_ISSUES_RESPONSE" | jq -r 'map(select(.pull_request == null)) | length')
68150
69151
OPEN_ISSUES_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
70-
"https://api.github.com/repos/$OWNER/$REPO/issues?state=open&per_page=100")
152+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/issues?state=open&per_page=100")
71153
OPEN_ISSUES=$(echo "$OPEN_ISSUES_RESPONSE" | jq -r 'map(select(.pull_request == null)) | length')
72154
73155
CLOSED_ISSUES=$((ALL_ISSUES - OPEN_ISSUES))
74156
75157
PRS_RESPONSE=$(curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
76-
"https://api.github.com/repos/$OWNER/$REPO/pulls?state=all&per_page=100")
158+
"https://api.github.com/repos/$CHECK_OWNER/$CHECK_REPO/pulls?state=all&per_page=100")
77159
PR_COUNT=$(echo "$PRS_RESPONSE" | jq -r 'length')
78160
79161
STAR_WEIGHT=10
80162
ISSUE_WEIGHT=20
81163
PR_WEIGHT=30
82164
83165
ARTICLE_BONUS=${{ env.article_bonus }}
166+
LESSON1_SCORE=${{ env.lesson1_score || 0 }}
167+
LESSON2_SCORE=${{ env.lesson2_score || 0 }}
84168
85169
SCORE=$((STARS * STAR_WEIGHT + CLOSED_ISSUES * ISSUE_WEIGHT + PR_COUNT * PR_WEIGHT + ARTICLE_BONUS))
170+
LESSON_SCORE=$((LESSON1_SCORE + LESSON2_SCORE))
86171
87172
echo "=================== 学员成绩报告 ==================="
88173
echo "Stars: $STARS (权重: $STAR_WEIGHT) = $((STARS * STAR_WEIGHT)) 分"
89174
echo "已解决的Issues: $CLOSED_ISSUES (权重: $ISSUE_WEIGHT) = $((CLOSED_ISSUES * ISSUE_WEIGHT)) 分"
90175
echo "Pull Requests: $PR_COUNT (权重: $PR_WEIGHT) = $((PR_COUNT * PR_WEIGHT)) 分"
91-
echo "个人文章提交: $ARTICLE_EXISTS (权重: 20) = $ARTICLE_BONUS 分"
176+
echo "个人文章提交: ${{ env.article_exists }} (权重: 20) = $ARTICLE_BONUS 分"
177+
echo "Lesson1作业: ${{ env.lesson1_exists }} (权重: 10) = $LESSON1_SCORE 分"
178+
echo "Lesson2作业: ${{ env.lesson2_exists }} (权重: 10) = $LESSON2_SCORE 分"
92179
echo "=================================================="
93180
echo "总分: $SCORE 分"
181+
echo "课程作业总分: $LESSON_SCORE 分"
94182
echo "更新时间: $(date)"
95183
96184
echo "stars=$STARS" >> $GITHUB_ENV
97185
echo "issues=$CLOSED_ISSUES" >> $GITHUB_ENV
98186
echo "prs=$PR_COUNT" >> $GITHUB_ENV
99187
echo "score=$SCORE" >> $GITHUB_ENV
188+
echo "lesson_score=$LESSON_SCORE" >> $GITHUB_ENV
189+
echo "student_name=$STUDENT_NAME" >> $GITHUB_ENV
100190
101191
- name: Post summary JSON to remote API
102192
run: |
103-
REPO_NAME=${{ github.repository }}
104-
OWNER=$(echo $REPO_NAME | cut -d'/' -f1)
105-
REPO=$(echo $REPO_NAME | cut -d'/' -f2)
106-
107-
ACTOR=${{ github.actor }}
193+
STUDENT_NAME=${{ env.student_name }}
108194
195+
# 使用加密的配置信息(base64 编码)
109196
ENCRYPTED_CONFIG="QVBJX1RPS0VOPWUzNjE5Y2NkZGFmYzQ3NTg5YmJlNzg4Y2EzMWEyZGYwCkFQSV9VUkw9aHR0cHM6Ly9hcGkub3BlbmNhbXAuY24vd2ViL2FwaS9jb3Vyc2VSYW5rL2NyZWF0ZUJ5VGhpcmRUb2tlbgpDT1VSU0VfSUQ9MTk0OAo="
110197
111198
echo "$ENCRYPTED_CONFIG" | base64 -d > /tmp/decrypted-config.env
@@ -116,7 +203,7 @@ jobs:
116203
"channel": "github",
117204
"courseId": $COURSE_ID,
118205
"ext": "aaa",
119-
"name": "$ACTOR",
206+
"name": "$STUDENT_NAME",
120207
"score": ${{ env.score }},
121208
"totalScore": 9999
122209
}
@@ -130,4 +217,39 @@ jobs:
130217
-d "$SUMMARY" \
131218
-v
132219
133-
rm /tmp/decrypted-config.env
220+
rm /tmp/decrypted-config.env
221+
222+
- name: Post lesson assignments score to remote API
223+
if: github.event_name == 'pull_request'
224+
run: |
225+
STUDENT_NAME=${{ env.student_name }}
226+
227+
# 使用加密的配置信息(base64 编码)
228+
# 原始内容:API_URL=https://api.opencamp.cn/web/api/courseRank/createByThirdToken
229+
# API_TOKEN=f7071e69e65d4d0587e0333420ca84a0
230+
# COURSE_ID=1945
231+
ENCRYPTED_LESSON_CONFIG="QVBJX1VSTD1odHRwczovL2FwaS5vcGVuY2FtcC5jbi93ZWIvYXBpL2NvdXJzZVJhbmsvY3JlYXRlQnlUaGlyZFRva2VuCkFQSV9UT0tFTj1mNzA3MWU2OWU2NWQ0ZDA1ODdlMDMzMzQyMGNhODRhMApDT1VSU0VfSUQ9MTk0NQo="
232+
233+
echo "$ENCRYPTED_LESSON_CONFIG" | base64 -d > /tmp/lesson-config.env
234+
source /tmp/lesson-config.env
235+
236+
LESSON_SUMMARY=$(cat <<EOF
237+
{
238+
"channel": "github",
239+
"courseId": $COURSE_ID,
240+
"ext": "lesson_assignments",
241+
"name": "$STUDENT_NAME",
242+
"score": ${{ env.lesson_score }},
243+
"totalScore": 20
244+
}
245+
EOF
246+
)
247+
248+
curl -X POST "$API_URL" \
249+
-H "accept: application/json;charset=utf-8" \
250+
-H "Content-Type: application/json" \
251+
-H "token: $API_TOKEN" \
252+
-d "$LESSON_SUMMARY" \
253+
-v
254+
255+
rm /tmp/lesson-config.env

README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,34 @@ Upstream 这个代码仓用于帮助商业训练营的同学们完成作业。
1818
8. 提交PR
1919
9. 完成实验后,可以在训练营官网排行榜处查看成绩 [导学阶段 - 第一期源起之道开源商业创新营 - 源起之道开源商业创新营 - 训练营](https://opencamp.cn/UpstreamLabs/camp/S1/stage/0?tab=rank)
2020

21+
## 基础阶段第一课作业
22+
23+
### 作业要求
24+
[assignments/lesson1](assignments/lesson1) 目录下,选择以下任一开源商业模式进行分析,并提交分析报告:
25+
- Odoo 商业模式
26+
- 安卓商业模式
27+
- 红帽商业模式
28+
- Linux 基金会商业模式
29+
- Apache 商业模式
30+
31+
### 提交方式
32+
1. 复制 [assignments/lesson1/example-report.md](assignments/lesson1/example-report.md) 并重命名为您的 GitHub 用户名
33+
2. 按照模板要求完成分析报告
34+
3. 提交 Pull Request
35+
36+
## 基础阶段第二课作业:Git工具实践
37+
38+
### 作业要求
39+
1. 完成版本控制工具git安装,通过执行`git --version`查看版本信息,并截图
40+
2. fork仓库 https://github.com/upstreamlabs/github101 到自己账号下,将个人账号下的github101(可以是fork时自定义项目名)克隆到本地(指操作设备),在[assignments/lesson2](assignments/lesson2)目录下创建以个人账号(GitHub账号)命名的markdown文件,在文件中撰写git安装过程、遇到的问题及解决方法,以及使用命令查看版本信息的截图。
41+
3. 通过git命令将本地仓库提交到远程仓库(个人账号),向远程仓库(组织仓)提交PR合入请求。
42+
4. 将使用git命令过程总结记录到第2步中的markdown文件,最后再次执行第3步操作提交。
43+
44+
### 提交方式
45+
1. 复制 [assignments/lesson2/example-report.md](assignments/lesson2/example-report.md) 并重命名为您的 GitHub 用户名
46+
2. 按照模板要求完成实践报告
47+
3. 提交 Pull Request
48+
2149
## 自动评分系统
2250

2351
本仓库包含一个自动评分系统,用于评估学员在GitHub上的参与度和贡献。评分系统会根据以下指标自动计算分数:
@@ -41,5 +69,23 @@ Upstream 这个代码仓用于帮助商业训练营的同学们完成作业。
4169
### 如何查看自己的分数
4270

4371
- 系统每天北京时间早上8点自动运行计算分数
44-
- 每次向仓库push代码时也会触发分数计算
45-
- 可以通过GitHub Actions界面手动触发计算
72+
- 每次向仓库 push 到 main 分支时触发分数计算
73+
- 可在 GitHub Actions 界面手动触发计算(首次 Fork 需手动运行)
74+
75+
#### 自动评分系统(CI)运行说明
76+
- 工作流文件: [.github/workflows/calculate-score.yml](.github/workflows/calculate-score.yml)
77+
- 触发条件:
78+
- 定时:每天 08:00(北京时区,UTC 00:00)
79+
- push:推送到 main 分支
80+
- pull_request:向 main 分支发起或更新 PR(用于课程作业检测)
81+
- 手动:在 Actions 页面使用 Run workflow
82+
- 课程作业检测仅在 PR 事件时执行。请通过 PR 提交作业文件:
83+
- Lesson1:assignments/lesson1/{你的GitHub用户名}.md
84+
- Lesson2:assignments/lesson2/{你的GitHub用户名}.md
85+
- 个人文章检测文件名:仓库根目录 {你的GitHub用户名}.md
86+
87+
#### 首次 Fork 后手动运行指引
88+
1. 打开你 Fork 后的仓库的 GitHub 页面,点击 Actions
89+
2. 左侧选择 Calculate Student Score 工作流
90+
3. 点击 Run workflow,选择分支 main,确认运行
91+
4. 运行完成后在 Jobs 的日志中查看成绩报告

XiaoKuge.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1-
# 小酷哥的文章
1+
# 小酷哥的文章(示例)
22

33
在今天的商业训练营的开源项目的产品经理的课程里,我了解到如何成为一个AI时代的个人创业者Solopreneur的一些知识和信息。
44

55
Solopreneurs的特点是:
66
1. 他们动作很快,快速Build,快速试错。
77
2. 他们只build自己用的产品。
88
3. 他们的产品不需要维护。
9+
10+
---
11+
12+
## CI 自动评分与运行指引
13+
- 个人文章检测文件名:仓库根目录 {你的GitHub用户名}.md(例如:XiaoKuge.md)
14+
- 课程作业检测仅在 PR 到 main 时执行,请通过 Pull Request 提交作业:
15+
- Lesson1:assignments/lesson1/{你的GitHub用户名}.md
16+
- Lesson2:assignments/lesson2/{你的GitHub用户名}.md
17+
- 自动评分工作流: [.github/workflows/calculate-score.yml](.github/workflows/calculate-score.yml)
18+
- 首次 Fork 后手动运行:
19+
1. 打开你 Fork 后的仓库页面,点击 Actions
20+
2. 选择 “Calculate Student Score” 工作流
21+
3. 点击 “Run workflow”,选择分支 main 并运行
22+
4. 在 Jobs 日志中查看成绩报告
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 开源商业模式分析报告模板
2+
3+
## 学员GitHub用户名: example-user
4+
5+
## 选择的商业模式
6+
(在此处填写您选择分析的开源商业模式,例如:Odoo 商业模式、安卓商业模式等)
7+
8+
## 分析内容
9+
10+
### 1. 商业模式概述
11+
(简要描述该开源项目的商业模式)
12+
13+
### 2. 收入来源
14+
(分析该项目的主要收入来源,如:订阅服务、技术支持、培训、云服务等)
15+
16+
### 3. 社区与生态
17+
(描述该项目的社区规模、生态系统建设情况)
18+
19+
### 4. 竞争优势
20+
(分析该商业模式相比传统商业软件的优势)
21+
22+
### 5. 挑战与风险
23+
(指出该商业模式面临的挑战和潜在风险)
24+
25+
### 6. 个人见解
26+
(分享您对该商业模式的看法和思考)
27+
28+
---
29+
30+
## CI 自动评分与运行指引
31+
- 课程作业检测仅在 PR 到 main 时执行,请通过 Pull Request 提交本文件。
32+
- 文件命名:assignments/lesson1/{你的GitHub用户名}.md。
33+
- 自动评分工作流: [.github/workflows/calculate-score.yml](../../.github/workflows/calculate-score.yml)
34+
- 首次 Fork 后:进入 Actions → 选择 “Calculate Student Score” → 点击 “Run workflow” 并选择 main → 在日志中查看成绩。

0 commit comments

Comments
 (0)