Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Github Actions 로 Android 팀의 효율성 극대화
Search
Harada Ha
July 21, 2024
Technology
0
270
Github Actions 로 Android 팀의 효율성 극대화
Google I/O extended Android 2024 때 발표한 자료 입니다.
Harada Ha
July 21, 2024
Tweet
Share
More Decks by Harada Ha
See All by Harada Ha
빠른 안드로이드 개발에 대한 프로세스 알아보기
hadonghyun
0
650
Privacy Changes in Android Q
hadonghyun
1
410
지금까지 이런 간단한 Logic 처리는 없었다 이것은 Rx 인가, UI 이벤트인가? 네, RxBinding입니다.
hadonghyun
1
220
Other Decks in Technology
See All in Technology
IAMのマニアックな話2025
nrinetcom
PRO
6
1.5k
プロダクト開発者目線での Entra ID 活用
sansantech
PRO
0
170
DeepSeekとは?何がいいの? - Databricksと学ぶDeepSeek! 〜これからのLLMに備えよ!〜
taka_aki
2
190
RaspberryPi CM4(CM5も)面白いぞ!
nonnoise
1
180
AIエージェント時代のエンジニアになろう #jawsug #jawsdays2025 / 20250301 Agentic AI Engineering
yoshidashingo
9
4.3k
30→150人のエンジニア組織拡大に伴うアジャイル文化を醸成する役割と取り組みの変化
nagata03
0
380
Cracking the Coding Interview 6th Edition
gdplabs
14
28k
貧民的プログラミングのすすめ
kakehashi
PRO
2
190
サイト信頼性エンジニアリングとAmazon Web Services / SRE and AWS
ymotongpoo
7
1.9k
JAWS FESTA 2024「バスロケ」GPS×サーバーレスの開発と運用の舞台裏/jawsfesta2024-bus-gps-serverless
ma2shita
3
410
4th place solution Eedi - Mining Misconceptions in Mathematics
rist
0
150
QAエンジニアが スクラムマスターをすると いいなぁと思った話
____rina____
0
190
Featured
See All Featured
Scaling GitHub
holman
459
140k
Writing Fast Ruby
sferik
628
61k
Navigating Team Friction
lara
183
15k
Making Projects Easy
brettharned
116
6k
How to Ace a Technical Interview
jacobian
276
23k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
4
390
Producing Creativity
orderedlist
PRO
344
40k
Designing on Purpose - Digital PM Summit 2013
jponch
117
7.1k
Facilitating Awesome Meetings
lara
53
6.3k
Building Better People: How to give real-time feedback that sticks.
wjessup
367
19k
Faster Mobile Websites
deanohume
306
31k
Building Your Own Lightsaber
phodgson
104
6.2k
Transcript
하동현 / @harada.ha Github Actions 로 Android 팀의 효율성 극대화
성장하는 팀, 늘어나는 업무: Github Actions 도입 배경 Section 1
H사 2 ~ 3명 Section 1 # 소통의 용이함 #
자원 부족 # 단순한 관리
B사 5 ~ 8명 Section 1 # 소통의 복잡성 증가
# 복잡한 워크플로우 # 안정된 운영
K사 10명 Section 1 # 향상된 안정성 # 관리 오버헤드
K사 bitrise B사 Github Actions Section 1
Github Actions Section 1
Github Actions 개요
Github Actions Section 1 # CI / CD
Event Runner 1 Runner 2 Job 1 Job 2 Runner
1 Runner 2 Step 1 : Run action Step 2 : Run script Step 1 : Run action Section 1
pull_request, issue_comment, workflow_dispatch, … Events on : pull_request : types
: [opened, synchronize] Section 1
Event Runner 1 Runner 2 Job 1 Job 2 Runner
1 Runner 2 Step 1 : Run action Step 2 : Run script Step 1 : Run action Section 1
Event Runner 1 Runner 2 Job 1 Job 2 Runner
1 Runner 2 Step 1 : Run action Step 2 : Run script Step 1 : Run action Section 1
Job 을 구성하는 작은 단계 Actions steps : # 체크아웃
액션: 저장소의 코드를 체크아웃 - - name : Check out Code uses : actions/checkout@v3 # 액션: 코드 컴파일 - name : Build the project run : ./gradlew assembleDebug Section 1
Event Runner 1 Runner 2 Job 1 Job 2 Runner
1 Runner 2 Step 1 : Run action Step 2 : Run script Step 1 : Run action Section 1
None
효율적인 워크플로우 구축: Github Action 적용 사례 Section 2
Android PR Board Section 2
Android PR Board Section 2
- Ts : 수동으로 카드 하나를 생성하는 데 걸리는 시간
= 20초 - R : PR 당 리뷰어의 수 = 2명 - P : PR의 수 = 3개 - C : 총 생성해야 하는 카드의 수 = R×P = 6개 Total_s = C×Ts = 6×20 = 2분 PR 카드 생성 시간 Section 2 Section 2
PR 카드 생성 시간 Section 2 1일 기준 = 2분
× 5명 = 10분 근무 21일 기준 = 210분 = 3.5시간
GitHub Docs Section # Section 2
PR 카드 생성 자동화로 시간 절약 3.5H Save Section #
Section 2
PR Review Workflow
PR Review Workflow Section 2 /review @notifier, @notifier
PR Review Workflow Section 2 set-reviewers
PR Review Workflow Section # Section 2 create-card
PR Review Workflow Section # PR Card Section 2 move-card
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
PR Comment
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
PR Comment Section 2 /review @notifier, @notifier
https://docs.github.com/ko/actions/using-workflows/events-that-trigger-workflows Events on : issue_comment : types : [created] Section
2 - created - edited - deleted
Jobs Section 2 jobs : pr_comment : if : github.event.issue.pull_request
&& startsWith(github.event.comment.body, '/review' ) steps : - name : Dispatch . . .
https://github.com/actions/github-script Actions steps : # PR comment 분석하여 리뷰어 추출
후, review-pr-card 워크 플로우 트리거 - - name : Dispatch uses : actions/github-script@v7 with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | Section 1 Section 2
- name : dispatch uses : actions/github-script@v7 with : github-token
: ${{ secrets.GITHUB_TOKEN }} script : | const[ , …reviewParameters] = '${{ github.event.comment.body }}'.trim().split(' ') . . . await github.rest.actions.createWorkflowDispatch({ . . .context.repo, workflow_id : 'action-pipelines-review-pr-card.yml', ref : context.ref, inputs : { pr_number: `${ context.issue.number }`, . . . } });
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-automation column_id find-card set-reviewers create-card move-card outputs
PR Board Section # Section 2 Assignee Reviewer PR Data
- name : dispatch . . . with : script
: | . . . await github.rest.actions.createWorkflowDispatch({ . . .context.repo, workflow_id : 'action-pipelines-review-pr-card.yml', ref : context.ref, inputs : { pr_number: `${ context.issue.number }`, pr_assignee: `${ commentUser }`, pr_reviewers = `${ notifiers.join() }` } });
Review PR Card
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
on : workflow_dispatch : inputs : pr_number : description :
'PR number' required : true default : ' ' pr_assignee : . . . pr_reviewers : . . . jobs : prepare : runs-on : [self-hosted, amd64, small, spot] steps : . . .
None
prepare pr_data review-pr-card pr-review column_id find-card set-reviewers create-card move-card pr_html_url
pr_title outputs
PR Card Section # pr_title pr_html_url Section 2
prepare : steps : - name : get-pr-data uses :
actions/github-script@v7 id : pr_data with : script : | . . . return pr_data - name : get-pr-url . . . script : | const prData = ${{ steps.pr_data.outputs.result }} return prData.html_url result-encoding : string
prepare : steps : - name : get-pr-data uses :
actions/github-script@v7 id : pr_data with : script : | . . . return pr_data - name : get-pr-url . . . script : | const prData = ${{ steps.pr_data.outputs.result }} return prData.html_url result-encoding : string
prepare pr_data review-pr-card pr-review column_id find-card set-reviewers create-card move-card pr_assignee_column_id
pr_reviewers_column_id outputs Section 2
PR Board Section # Section 2 pr_assignee_column_id pr_reviewers_column_id
prepare : steps : . . . - name :
checkout uses : actions/checkout@v3 - name : pr-assignee-to-project-column-id run : chmod +x ./column.sh result=$(./column.sh "${{ github.event.inputs.pr_assignee }}") echo "result=${result}" >> $GITHUB_OUTPUT . . .
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
jobs : prepare : steps : - name : get-pr-data
- name : get-pr-url . . . outputs : pr_html_url : ${{ steps.pr_html_url.outputs.result }} pr_title : ${{ steps.pr_title_url.outputs.result }} pr_assignee_column_id : ${{ steps.pr-assignee-to-project-column-id.outputs.result }} . . . pr-automation : . . .
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
jobs : prepare : steps : - name : get-pr-data
- name : get-pr-url . . . pr-review : needs : [ prepare ] steps : - name : find-card - name : set-reviewers - name : create-card - name : move-card
jobs .<job_id> .needs Section # Section 2
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
Find Card Section # Section 2 기존에 카드가 존재 했을
경우
- name : find-card uses : actions/github-script@v7 id : find_card
with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | const { data: listCards } = await github.rest.projects.listCards({ column_id : columnId, }); . . . if (card) { return card.id } else { return 0 }
- name : find-card uses : actions/github-script@v7 id : find_card
with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | const { data: listCards } = await github.rest.projects.listCards({ column_id : colinmId, }); . . . if (card) { return card.id } else { return 0 }
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
- name : set-reviewers if : steps.find_card.outputs.result == 0 uses
: actions/github-script@v7 with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | const { data: requestedReviewers } = await github.rest.pulls.listRequestedReviewers({ column_id : colinmId, }); . . . if (requestedReviewers.users.length === 0) { await github.rest.pulls.requestReviewers({ . . . }} }
- name : set-reviewers if : steps.find_card.outputs.result == 0 uses
: actions/github-script@v7 with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | const { data: requestedReviewers } = await github.rest.pulls.listRequestedReviewers({ column_id : colinmId, }); . . . if (requestedReviewers.users.length === 0) { await github.rest.pulls.requestReviewers({ . . . }} }
PR Reviewers State Section 2 approved requested-reviewer
- name : set-reviewers if : steps.find_card.outputs.result == 0 uses
: actions/github-script@v7 with : github-token : ${{ secrets.GITHUB_TOKEN }} script : | const { data: requestedReviewers } = await github.rest.pulls.listRequestedReviewers({ column_id : colinmId, }); . . . if (requestedReviewers.users.length === 0) { await github.rest.pulls.requestReviewers({ . . . }} }
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data review-pr-card
pr-review column_id find-card set-reviewers create-card move-card outputs
PR Review Card Section # PR Card Section 2
찾아온 위기: Projects Sunset
Projects (classic) sunset Section 2
PR Review Section 2 팀원들이 PR을 잘 볼 수 있는
방법 없을까?
GitHub Integration Section # Section 2
Slack Github Action Section # Section 2
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data pr-review
github_username set-reviewers notify-reviewers send-dm-for- reviewer outputs notify-pr-reviewer pr_title pr_url pr_assignee pr_reviewer
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data pr-review
github_username set-reviewers notify-reviewers send-dm-for- reviewer outputs notify-pr-reviewer pr_title pr_url pr_assignee pr_reviewer
- name : notify-reviewers uses : actions/github-script@v7 with : github-token
: ${{ secrets.GITHUB_TOKEN }} script : | . . . for (const reviewer of selectedReviewers) { await github.rest.actions.createWorkflowDispatch({ . . . context.repo, workflow_id : 'action-pipelines-notify-pr-reviewer.yml', inputs: { . . . } } }
PR Reviewers Section 2 notify-pr-reviewer notify-pr-reviewer notify-pr-reviewer
pr_comment prepare /review @notifier, @notifier pr_number pr_assignee pr_reviewers pr_data pr-review
github_username set-reviewers notify-reviewers send-dm-for- reviewer outputs notify-pr-reviewer pr_title pr_url pr_assignee pr_reviewer
- name : send-dm-for-reviewer uses : slackapi/
[email protected]
env : SLACK_BOT_TOKEN
: ${{ secrets.SLACK_ANDROID_PR_BOT_TOKEN }} with : channel-id : ${{ steps.pr_reviewer_slack_mention_token.outputs.result }} payload : | { "blocks" : [ { "type" : "header", "text" : { "type" : "plain_text", "text" : "PR 리뷰 부탁드립니다 :pray:", "emoji" : true } . . .
Slack API Your Apps Section # Section 2
Slack Bot Token Section # https://api.slack.com/tutorials/tracks/getting-a-token Section 2
Slack Bot Token Scopes Section # Section 2
GitHub Repository Settings Section # Section 2
- name : send-dm-for-reviewer uses : slackapi/
[email protected]
env : SLACK_BOT_TOKEN
: ${{ secrets.SLACK_ANDROID_PR_BOT_TOKEN }} with : channel-id : ${{ steps.pr_reviewer_slack_mention_token.outputs.result }} payload : | { "blocks" : [ { "type" : "header", "text" : { "type" : "plain_text", "text" : "PR 리뷰 부탁드립니다 :pray:", "emoji" : true } . . .
- name : send-dm-for-reviewer uses : slackapi/
[email protected]
env : SLACK_BOT_TOKEN
: ${{ secrets.SLACK_ANDROID_PR_BOT_TOKEN }} with : channel-id : ${{ steps.pr_reviewer_slack_mention_token.outputs.result }} payload : | { "blocks" : [ { "type" : "header", "text" : { "type" : "plain_text", "text" : "PR 리뷰 부탁드립니다 :pray:", "emoji" : true } . . .
Slack Channel-Id Section # Section 2
Slack Channel-Id Section # Section 2 https://api.slack.com/types/channel channel-id example: C1H9RESGL
Slack Channel-Id Section # Section 2
Slack Mention Section # Section 2 channel-id : C1H9RESGL mention
: <@U0G9QF9C6>
- name : send-dm-for-reviewer uses : slackapi/
[email protected]
env : SLACK_BOT_TOKEN
: ${{ secrets.SLACK_ANDROID_PR_BOT_TOKEN }} with : channel-id : ${{ steps.pr_reviewer_slack_mention_token.outputs.result }} payload : | { "blocks" : [ { "type" : "header", "text" : { "type" : "plain_text", "text" : "PR 리뷰 부탁드립니다 :pray:", "emoji" : true } . . .
Slack Block Kit Builder Section # Section 2
Slack Block Kit Builder Section # Section 2
Slack Block Kit Builder Section # Section 2
- name : send-dm-for-reviewer uses : slackapi/
[email protected]
env : SLACK_BOT_TOKEN
: ${{ secrets.SLACK_ANDROID_PR_BOT_TOKEN }} with : channel-id : ${{ steps.pr_reviewer_slack_mention_token.outputs.result }} payload : | { "blocks" : [ { "type" : "header", "text" : { "type" : "plain_text", "text" : "PR 리뷰 부탁드립니다 :pray:", "emoji" : true } . . .
Android PR Bot Section # Section 2
PR Review Reminder
PR Review Reminder Section 2 Slack DM으로 PR 메시지가 오는데
자꾸 까먹네... PR을 잘 볼 수 있는 방법 없을까?
PR Review Reminder Section 2 매일 오후 1시에 슬랙 알람이
온다면.. D-day 라벨을 붙이면..
pr-remind find-open-pr get-slack-mention- token notify-pr-list-to-reviewer payload pr_reviewer prepare-slack-message send-dm-for- reviewer
on : schedule : # 평일 13시 실행 cron :
'0 4 * * 1-5' workflow_dispatch : jobs : pr-remind : . . . steps : - name : find-open-pr - name : prepare-slack-message . . .
Slack Block Kit Builder Section # Section 2
pr-remind find-open-pr get-slack-mention- token notify-pr-list-to-reviewer payload pr_reviewer prepare-slack-message send-dm-for- reviewer
- name : find-open-pr . . . script : |
const { data : pullRequests } = await github.rest.pulls.list({ . . . }); const filteredPullRequests = pullRequests.filter(pr => pr.requested_reviewers.length !=0 && !pr.draft ); return filteredPullRequests
- name : find-open-pr . . . script : |
const { data : pullRequests } = await github.rest.pulls.list({ . . . }); const filteredPullRequests = pullRequests.filter(pr => pr.requested_reviewers.length !=0 && !pr.draft ); return filteredPullRequests
Error Section # Section 2
pr-remind find-open-pr get-slack-mention- token notify-pr-list-to-reviewer payload pr_reviewer prepare-slack-message send-dm-for- reviewer
- name : prepare-slack-message . . . script : |
. . . const payload = { blocks : [ . . . ] } await github.rest.actions.createWorkflowDispatch({ . . . inputs : { payload : JSON.stringfy(payload), pr_reviewer : `${ reviewer }` } })
Slack Block Kit Builder Section # Section 2
- name : prepare-slack-message . . . script : |
. . . const payload = { blocks : [ . . . ] } await github.rest.actions.createWorkflowDispatch({ . . . inputs : { payload : JSON.stringfy(payload), pr_reviewer : `${ reviewer }` } })
pr-remind find-open-pr get-slack-mention- token notify-pr-list-to-reviewer payload pr_reviewer prepare-slack-message send-dm-for- reviewer
pr-remind find-open-pr get-slack-mention- token notify-pr-list-to-reviewer payload pr_reviewer prepare-slack-message send-dm-for- reviewer
PR Reminder Section # Section 2
PR Review Reminder Section 2 Section 3
Github Actions, 그 이후 Section 3
Android Build Bot Section 2 Section 3
Android Build Bot Section 2 Section 3
PR Review Label Section 2 Section 3
Thank You 하동현 / @harada.ha Remember | ex-KakaoStyle