Slide 1

Slide 1 text

1 ࠷ۙ Fitbit Λ͚ͭͯࢄาͯ͠ΔͷͰ CircleCI + Pixela Ͱݟ͑ΔΑ͏ʹͯ͠Έͨ 2022-03-16 ࣗಈԽLTձɹʙࣗಈԽɾޮ཰Խେ޷͖ͳਓू·Εʂʙ ௣༿ ޫߦ (Twitter: @bufferings) Senior Full Stack Engineer, CircleCI

Slide 2

Slide 2 text

า͘ͱࣗಈͰ૲͕͸͑Δʔʂ 2 https://pixe.la/v1/users/bufferings/graphs/steps.html ΞΫηε೔ 2022-03-14

Slide 3

Slide 3 text

3 ௣༿ ޫߦ (Twitter: @bufferings) Senior Full Stack Engineer, CircleCI (2021೥10݄ʙ) ࣗݾ঺հ https://bufferings.hatenablog.com/entry/2022/02/27/150342

Slide 4

Slide 4 text

4 Free ϓϥϯͰ΋े෼ͳϏϧυ࣌ؒͰࣗಈԽՄೳ Free ϓϥϯͰ΋ 
 े෼ͳϏϧυ࣌ؒͰࣗಈԽՄೳ ɾຖ݄6,000෼૬౰ͷΫϨδο 
 ɹτΛ෇༩ɺ࠷దͳϦιʔε 
 ɹΫϥε (CPU/RAM) Λબ୒Մೳ ɾϢʔβʔ਺͸ແ੍ݶ͔ͩΒ 
 ɹνʔϜ։ൃʹ΋ద༻Մೳ ɾύϫϑϧͳϦιʔεΫϥεɺ 
 ɹDocker ίϯςφ΍VM(Linux, 
 ɹWindows, Mac)Λར༻Մೳ ಉ࣌ؒ͡࿮Ͱ΋ CircleCI ͳΒ 
 ར༻Մೳͳػೳ͕͜Μͳʹ΋ ɾεϐʔυͱύϑΥʔϚϯε͕ 
 ɹ޲্ɺDocker ίϯςφΛ࠷దԽ ɾϏϧυ͕ΑΓߴ଎Խɺ 
 ɹಉ࣌ʹ30ฒྻ࣮ߦ·ͰՄೳ ɾϓϥΠϕʔτ Orb Ͱ CI/CD ΋ 
 ɹίϥϘϨʔγϣϯɺઃఆͷ 
 ɹ෦඼Խɺ૊৫಺Ͱͷ࠶ར༻Մೳ 
 ɾϏϧυ࣌ؒ͸໿̎ഒɺࣗಈԽ 
 ɹͷ݁ՌΛΑΓૣ͘ಘΒΕ·͢ ϑΟʔυόοΫϧʔϓΛճ͠ 
 ιϑτ΢ΣΞΛૉૣ͘ಧ͚Δ ɾϏϧυ࣌ؒΛ୹ॖՄೳͳͷ͸ 
 ɹδϣϒΛฒྻ࣮ߦͰ͖Δ͔Β ɾΠϯςϦδΣϯτʹςετ 
 ɹ෼্ׂͨ͠Ͱฒྻ࣮ߦՄೳ 
 ɹ(ϑΝΠϧ਺ɺϑΝΠϧαΠζɺ 
 ɹ ϩά͔Βͷ࣮ߦ࣮࣌ؒ੷Ͱ෼ׂ) ɾΠϯαΠτػೳͰࣦഊ͕ͪ͠ 
 ɹͳςετ΍݁Ռ͕ෆ҆ఆͳςε 
 ɹτͳͲΛநग़Մೳ Ϣʔβʔొ࿥: https://circleci.com/ja/signup/ ྉۚϓϥϯ: https://circleci.com/ja/pricing/ αϙʔτ: https://support.circleci.com/hc/ja

Slide 5

Slide 5 text

5 ͦ͏ͩɺؾ෼స׵ʹίʔυΛॻ͜͏ʂ Fitbit Pixela

Slide 6

Slide 6 text

6 "ౙٳΈͷࣗ༝ݚڀ (3) ʙ Զ͸Ұ೔Ͳͷ͘Β͍૸ͬͯ (า͍ͯ) ͍Δͷ͔Λ Fitbit Web API ͱ pixela Λ࢖ͬͯՄࢹԽ͢Δݕূ CircleCI Λఴ͑ͯ ʙ" https://inokara.hateblo.jp/entry/2020/01/03/132348ɹ ΞΫηε೔ 2022-03-14 Α͏΁͍͞Μͷϒϩά

Slide 7

Slide 7 text

7 (1) Fitbit (2) Pixela (3) CircleCI ͦ͏ͩɺؾ෼స׵ʹίʔυΛॻ͜͏ʂ

Slide 8

Slide 8 text

8 Fitbit า਺Λऔಘ͢Δ

Slide 9

Slide 9 text

9 ❯ FITBIT_ACCESS_TOKEN="ΞΫηετʔΫϯ" ❯ curl -sX GET "https://api.fitbit.com/1/user/-/activities/steps/date/today/7d.json" \ -H "accept: application/json" \ -H "authorization: Bearer $FITBIT_ACCESS_TOKEN" \ | jq { "activities-steps": [ { "dateTime": "2022-02-21", "value": "7204" }, ... Fitbit API Ͱ௚ۙ7೔ؒͷา਺Λऔಘ (1) Fitbit → (3) CircleCI → (2) Pixela Get Activity Time Series by Date https://dev.fitbit.com/build/reference/web-api/activity-timeseries/get-activity-timeseries-by-date/

Slide 10

Slide 10 text

10 Fitbit API ͷΞΫηετʔΫϯΛऔಘ (1) Fitbit → (3) CircleCI → (2) Pixela 1. https://dev.fitbit.com/apps/new ͔ΒΞϓϦέʔγϣϯΛొ࿥ (*1) 2. OAuth 2.0 ͷ Authorization Code Flow ͰίʔυΛऔಘ (*2) 3. औಘͨ͠ίʔυΛ࢖༻ͯ͠τʔΫϯΛऔಘ ● (*1) ࣗ෼༻ͷμϛʔΞϓϦͳͷͰ URL ͸શ෦ localhost ͰOK ● (*2) OAuth 2.0 tutorial page ͕ศར

Slide 11

Slide 11 text

11 ❯ FITBIT_BASIC_TOKEN="Authorization: Basic ͷͱ͜ΖͷτʔΫϯ" ❯ FITBIT_REFRESH_TOKEN="ϦϑϨογϡτʔΫϯ" ❯ curl -sX POST "https://api.fitbit.com/oauth2/token" \ -H "accept: application/json" \ -H "authorization: Basic $FITBIT_BASIC_TOKEN" \ -d "grant_type=refresh_token&refresh_token=$FITBIT_REFRESH_TOKEN" \ | jq { "access_token": "৽͍͠ΞΫηετʔΫϯ", ... "refresh_token": "৽͍͠ϦϑϨογϡτʔΫϯ", ... Fitbit API ͰτʔΫϯΛϦϑϨογϡ (1) Fitbit → (3) CircleCI → (2) Pixela Refresh Token https://dev.fitbit.com/build/reference/web-api/authorization/refresh-token/

Slide 12

Slide 12 text

12 Fitbit API ͷ·ͱΊ (1) Fitbit → (3) CircleCI → (2) Pixela 1. ϦϑϨογϡτʔΫϯΛ࢖ͬͯ৽͍͠ΞΫηετʔΫϯͱϦϑϨογϡτʔΫϯΛ औಘ 2. ৽͍͠ΞΫηετʔΫϯΛ࢖ͬͯา਺Λऔಘ 3. ৽͍͠ϦϑϨογϡτʔΫϯ͸࣍ճͷͨΊʹอଘ͓ͯ͘͠

Slide 13

Slide 13 text

13 Pixela า਺Λॻ͖ࠐΉ

Slide 14

Slide 14 text

14 ❯ PIXELA_TOKEN="Pixela ʹొ࿥ͨ͠τʔΫϯ" ❯ curl -sX POST "https://pixe.la/v1/users/bufferings/graphs" \ -H "X-USER-TOKEN:$PIXELA_TOKEN" \ -d '{"id":"demo-lt","name":"demo-lt","unit":"steps","type":"int", "color":"ichou","timezone":"Asia/Tokyo"}' {"message":"Success.","isSuccess":true} Pixela API ͰάϥϑΛ࡞੒ (1) Fitbit → (3) CircleCI → (2) Pixela POST - /v1/users//graphs https://docs.pixe.la/entry/post-graph

Slide 15

Slide 15 text

15 ❯ curl -sX PUT "https://pixe.la/v1/users/bufferings/graphs/demo-lt/20220310" \ -H "X-USER-TOKEN:$PIXELA_TOKEN" \ -d '{"quantity": "5000"}' {"message":"Success.","isSuccess":true} Pixela API ͰσʔλΛొ࿥ (1) Fitbit → (3) CircleCI → (2) Pixela POST - /v1/users//graphs https://docs.pixe.la/entry/post-graph

Slide 16

Slide 16 text

16 Script ίʔυʹ͢Δ

Slide 17

Slide 17 text

17 TypeScript Ͱॻ͍͓͍ͯͨɿ https://github.com/bufferings/fitbit-to-pixela/blob/main/src/main.ts ίʔυʹ͢Δ (1) Fitbit → (3) CircleCI → (2) Pixela

Slide 18

Slide 18 text

18 CircleCI ࣗಈԽ͢Δ

Slide 19

Slide 19 text

Node.js ͷ Orb (https://circleci.com/developer/ja/orbs/orb/circleci/node) Λ࢖͏ͱศ རɻ͜Ε͚ͩͰ `npm run main` ͯ͘͠ΕΔɻΩϟογϡ΋໘౗Έͯ͘ΕΔɻ 19 config.yml Λ༻ҙ (1) Fitbit → (3) CircleCI → (2) Pixela

Slide 20

Slide 20 text

͋ͱ͸ Project Settings > Environment Variables ͔Β؀ڥม਺Λઃఆͯ͋͛͠Ε͹ಈ͘ • Fitbit ༻ ◦ FITBIT_BASIC_TOKEN ◦ FITBIT_REFRESH_TOKEN • Pixela ༻ ◦ PIXELA_GRAPH_URL ◦ PIXELA_TOKEN • CircleCI ༻ ◦ MY_CIRCLE_API_TOKEN ◦ MY_CIRCLE_PROJECT_SLUG 20 ϓϩδΣΫτʹ؀ڥม਺Λઃఆ (1) Fitbit → (3) CircleCI → (2) Pixela

Slide 21

Slide 21 text

User Settings > Personal API Tokens ͔ΒτʔΫϯΛੜ੒ 21 ৽͍͠ϦϑϨογϡτʔΫϯΛอଘ͢Δ (1) Fitbit → (3) CircleCI → (2) Pixela

Slide 22

Slide 22 text

22 ❯ MY_CIRCLE_PROJECT_SLUG="ϓϩδΣΫτͷύεɻྫ: github/bufferings/fitbit-to-pixela" ❯ MY_CIRCLE_API_TOKEN="ੜ੒ͨ͠τʔΫϯ" ❯ curl -sX POST "https://circleci.com/api/v2/project/${MY_CIRCLE_PROJECT_SLUG}/envvar" \ -H "circle-token: $MY_CIRCLE_API_TOKEN" \ -H "content-type: application/json" \ -d '{"name":"FITBIT_REFRESH_TOKEN","value":"xxxx12345"}' \ { "name" : "FITBIT_REFRESH_TOKEN", "value" : "xxxx2345" } ৽͍͠ϦϑϨογϡτʔΫϯΛอଘ͢Δ (1) Fitbit → (3) CircleCI → (2) Pixela Create an environment variable https://circleci.com/docs/api/v2/#operation/createEnvVar ͜Μͳײ͡Ͱߋ৽Ͱ͖ΔͷͰɺεΫϦϓτʹॻ͍͓͍ͯͨ

Slide 23

Slide 23 text

Project Settings > Triggers Ͱఆظ࣮ߦ͞ΕΔΑ͏ʹઃఆ 23 ఆظతʹ࣮ߦ͞ΕΔΑ͏ʹ͢Δ (1) Fitbit → (3) CircleCI → (2) Pixela

Slide 24

Slide 24 text

24 ఆظతʹ࣮ߦ͞ΕΔΑ͏ʹ͢Δ (1) Fitbit → (3) CircleCI → (2) Pixela ಈ͍ͨʔʂ

Slide 25

Slide 25 text

25 (1) Fitbit (2) Pixela (3) CircleCI

Slide 26

Slide 26 text

า͘ͱࣗಈͰ૲͕͸͑Δʔʂ 26 https://pixe.la/v1/users/bufferings/graphs/steps.html ΞΫηε೔ 2022-03-14

Slide 27

Slide 27 text

27 ݱࡏCircleCI JAPACΦϑΟεͰ͸ੵۃతʹԼهͷϙδγϣϯΛ࠾༻͓ͯ͠Γ·͢ʂ ● Staff Infrastructure Enginee r ● DevOps Customer Enginee r ● Senior Solutions Enginee r ● Sales Development Representativ e ● Enterprise Account Executiv e ● Commercial Account Executive, APA C ͋Γ͕ͱ͏͍͟͝·ͨ͠ʔʂ CircleCIͷ࠾༻৘ใ