Slide 1

Slide 1 text

Android ͷ੩తղੳʹ͓͚Δ SARIF ϑΝΠϧͷ׆༻ 2024.1.31 Android Test Night #9 Hiroyuki Kusu ( @hkusu_ )

Slide 2

Slide 2 text

About me

Slide 3

Slide 3 text

ຊ೔ͷ಺༰ • GitHub code scanning ͷ֓ཁ • CIʢGitHub ActionsʣͰ֤छ ੩తղੳπʔϧͱ GitHub code scanning Λ ࿈ܞ͢Δํ๏ͷઆ໌ • Android Lint • ktlint • mobsfscan • Qodana • CodeQL • GitHub code scanning Λ࢖Θͳ͍৔߹ͷ SARIF ϑΝΠϧͷ׆༻

Slide 4

Slide 4 text

• ֤छ ੩తղੳπʔϧࣗମͷ࢖͍ํ΍ݕग़ϧʔϧͷઃఆ • ຊདྷ͸ϧʔϧΛਫ਼ࠪ͠ɺద੾ʹπʔϧ΁ద༻ɾӡ༻͠ͳ͍ͱɺݕग़͕ ա৒Ͱ͋ͬͨΓෆ଍ͨ͠Γ͢Δ • ֤ϧʔϧͷΤϥʔϨϕϧͷௐ੔΋దٓ ඞཁ ຊ೔ ࿩͞ͳ͍͜ͱ .. ద੾ʹӡ༻͢Δͷ͸Ҏ֎ʹ೉͔ͬͨ͠Γ͢Δɻ໰୊Λݕग़͚ͩͯ͠์ஔͱ͍ ͏ͷ͸Α͋͘Γ͕ͪ

Slide 5

Slide 5 text

GitHub code scanning

Slide 6

Slide 6 text

GitHub code scanning • ϦϙδτϦ಺ͷίʔυΛ෼ੳͯ͠ɺηΩϡϦςΟͷ੬ऑੑͱίʔσΟϯά ΤϥʔΛݟ͚ͭΔ͜ͱ͕Ͱ͖Δػೳ • CodeQLʢGitHub ͕։ൃͨ͠ίʔυ෼ੳΤϯδϯʣΛ࢖༻ͯ͠ίʔυΛ ෼ੳ͠ɺ݁ՌΛΞϥʔτͱͯ͠දࣔ͢Δ͜ͱ͕ग़དྷΔ • private ϦϙδτϦͰ͸ GitHub Advanced Security ͷϥΠηϯεʢ༗ྉʣ ͕ඞཁ

Slide 7

Slide 7 text

GitHub code scanning Ұཡը໘

Slide 8

Slide 8 text

GitHub code scanning ৄࡉը໘ ཤྺ

Slide 9

Slide 9 text

ϓϧϦΫͰมߋͨ͠ߦʹ໰୊͕͋Δ৔߹ GitHub code scanning

Slide 10

Slide 10 text

• CodeQL Ҏ֎ͷ੩తղੳπʔϧͰ΋ར༻Ͱ͖Δ • CI Ͱ SARIF ܗࣜͷϨϙʔτΛΞοϓϩʔυ͢Ε͹Α͍ • SARIFɿ Static Analysis Results Interchange Format ͷུ GitHub code scanning

Slide 11

Slide 11 text

{ "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", "version": "2.1.0", "runs": [ { "originalUriBaseIds": { "%SRCROOT%": { "uri": "file:///home/runner/" } }, "results": [ { "level": "error", "locations": [ { "physicalLocation": { "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" }, "region": { "startColumn": 5, "startLine": 19 } } } ], "message": { "text": "Function name should start with a lowercase letter (except factory methods) and use camel case" }, "ruleId": "standard:function-naming" }, … ], "tool": { "driver": { "downloadUri": "https://github.com/pinterest/ktlint/releases/tag/1.0.1", "fullName": "ktlint", "informationUri": "https://github.com/pinterest/ktlint/", "language": "en", "name": "ktlint", "organization": "pinterest", "rules": [], "semanticVersion": "1.0.1", "version": "1.0.1" } } } ] } ktlint ͷ SARIF ϑΝΠϧͷྫ Schema ͷόʔδϣϯʢcode scanning ͸ 2.1.0 Λαϙʔτʣ ݕग़͞Εͨ໰୊ ࢖༻ͨ͠੩తղੳπʔϧͷ৘ใ πʔϧʹΑͬͯ͸ rules ཝʢͦΕҎ֎ͷ৔ॴͷ৔߹΋͋Δʣʹɺ֤ݕग़ϧʔϧ ͷิ଍৘ใ͕ॻ͔Ε͍ͯΔ

Slide 12

Slide 12 text

"results": [ { "level": "error", "locations": [ { "physicalLocation": { "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" }, "region": { "startColumn": 5, "startLine": 19 } } } ], "message": { "text": "Function name should start with a lowercase letter (except factory methods) and use camel case" }, "ruleId": "standard:function-naming" }, … ], ໰୊͕͋ΔϑΝΠϧͷύε ΤϥʔϨϕϧɻ͜͜Ͱ͸ͳ͘ rules ཝ౳ʹॻ͔Ε͍ͯΔ৔߹΋͋Δ ໰୊ͷίʔυͷҐஔɻπʔϧʹΑͬͯ͸։࢝Ґஔ͚ͩͰ ͳ͘ऴྃҐஔ΋ॻ͔Ε͍ͯΔ৔߹΋͋Δ ໰୊ͷ಺༰ͷςΩετ ݕग़ʹར༻ͨ͠ϧʔϧͷIDɻ͜ͷ ID ʹؔ͢Δิ଍৘ใ͕ rules ཝ౳ ʹॻ͔Ε͍ͯΔ৔߹͕͋Δ results ཝΛ֦େ

Slide 13

Slide 13 text

GitHub code scanning ֤πʔϧͷεςʔλεը໘ ֤πʔϧͷ SARIF ϑΝΠϧ Ξοϓϩʔυޙ

Slide 14

Slide 14 text

Android Lint × GitHub code scanning

Slide 15

Slide 15 text

android { ... lint { sarifReport = true checkDependencies = true } } • SARIF ܗࣜͰϨϙʔτΛग़ྗ͢Δઃఆ • ϚϧνϞδϡʔϧߏ੒ͷ৔߹Ͱ΋ɺϧʔτͷϞδϡʔϧͰ checkDependencies = true Λࢦఆ͢Ε͹ɺαϒϞδϡʔϧࠐΈͷϨϙʔτ͕࡞੒͞ΕΔ Android Lint × GitHub code scanning app/build.gradle.kts

Slide 16

Slide 16 text

name: CI on: push: branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew app:lintDebug continue-on-error: true - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ./app/build/reports/lint-results-debug.sarif category: android-lint:debug Android Lint × GitHub code scanning github/codeql-action/upload-sarif action ͷ࣮ߦͰඞཁͳ permission code scanning ͕ར༻Ͱ͖ΔϦϙδτϦͰͳ͍৔߹͸͜ͷ step ͸ΤϥʔͱͳΓ·͢

Slide 17

Slide 17 text

- run: ./gradlew app:lintDebug continue-on-error: true Android Lint × GitHub code scanning • ʢղੳॲཧ͕ਖ਼ৗʹऴΘͬͯ΋ʣ໰୊Λݕग़ͨ͠৔߹ʹऴྃίʔυ͕ 0 Ҏ֎ͱͳΔ੩తղੳ πʔϧͷ৔߹͸ continue-on-error: true Λࢦఆ • ϫʔΫϑϩʔ͕ fail εςʔλεͷ৔߹ɺcode scanning ͸ ղੳॲཧʹࣦഊ ͨ͠ͱΈͳ͢ • πʔϧଆͷઃఆͰɺͦ΋ͦ΋ҟৗऴྃ͠ͳ͍Α͏ʹͯ͠΋Α͍ • ྫ͑͹ Android Lint ͷ৔߹͸ abortOnError = false • ΋͘͠͸ ./gradlew app:lintDebug || true ͷΑ͏ʹͯ͠ҟৗऴྃΛѲΓ௵͢

Slide 18

Slide 18 text

Android Lint × GitHub code scanning - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ./app/build/reports/lint-results-debug.sarif category: android-lint:debug • category ʹ͸೚ҙͷจࣈྻΛࢦఆՄೳ • লུ͢ΔͱʮϫʔΫϑϩʔϑΝΠϧ໊:δϣϒ໊ʯͱͳΔ • ʢ޷Έͷ໰୊Ͱ͸͋Δ͕ʣ೦ͷͨΊলུͤͣʹࢦఆ͓͍ͯͨ͠ํ͕ແ೉ͱࢥΘΕΔ • কདྷతʹϫʔΫϑϩʔΛ੔ཧͨ݁͠Ռɺδϣϒ໊͕มΘͬͯ͠·͏͜ͱ΋͋ΓಘΔ • ্هͷྫͰ͸πʔϧ໊ʹՃ͑ͯɺͲͷόϦΞϯτʹର͢Δղੳͳͷ͔Λ : Ҏ߱Ͱදݱ͍ͯ͠Δ • ͨͩԾʹ్தͰ category ͕มΘͬͯ͠·ͬͯ΋ɺͳΜͱͳ͘͸ཤྺͷඥ͚ͮ͸͞ΕΔ

Slide 19

Slide 19 text

Android Lint × GitHub code scanning

Slide 20

Slide 20 text

ktlint × GitHub code scanning

Slide 21

Slide 21 text

val ktlintCheck by tasks.registering(JavaExec::class) { group = LifecycleBasePlugin.VERIFICATION_GROUP description = "Check Kotlin code style" classpath = ktlint mainClass.set("com.pinterest.ktlint.Main") args( "--color", "--reporter=plain", "--reporter=sarif,output=${buildDir}/reports/ktlint-results.sarif", "**/src/**/*.kt", "**.kts", "!**/build/**", ) // isIgnoreExitValue = true ҟৗऴྃͤ͞ͳ͍৔߹ } build.gradle.ktsʢϓϥάΠϯΛ࢖༻ͤͣʹ ktlint Λಋೖ͍ͯ͠Δ৔߹ʣ ktlint × GitHub code scanning

Slide 22

Slide 22 text

ktlint × GitHub code scanning name: CI on: push: branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew ktlintCheck continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint

Slide 23

Slide 23 text

ktlint × GitHub code scanning - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" } SARIF ϑΝΠϧͷՃ޻͕ඞཁ "artifactLocation": { "uri": “app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" } uri ͔Β work/your-repo/your-rep/ Λআڈ

Slide 24

Slide 24 text

ktlint × GitHub code scanning file:///home/runner/work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt or app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt GitHub code scanning Ͱ uri ͷύεΛਖ਼͘͠ೝࣝͤ͞Δʹ͸ɺ fi le:// ͔Β࢝·Δ CI ্ͷઈରύεɺ ΋͘͠͸ϦϙδτϦ௚ԼΛϧʔτͱ͢Δ૬ରύεͷͲͪΒͷܗࣜͰ͋Δඞཁ͕͋Δ SARIF ϑΝΠϧ಺ͷ SRCROOT Ͱ uri ͷϕʔεͷύε͕ఆٛ͞Ε͍ͯΔʢϕʔεͱ߹Θͤͯઈରύ εͱͳΔʣ৔߹͕͋Δ͕ɺcode scanning ͸ SRCROOT Λݟ͍ͯͳ͍

Slide 25

Slide 25 text

ktlint × GitHub code scanning - run: ./gradlew ktlintCheck --continue continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/")' \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint:app - run: | cat './shared/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr("work/your-repo/your-repo/")' \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint:shared 1ͭͷϞδϡʔϧͰҟৗऴ͕ྃ͋ͬͯ΋ܧଓ͢ΔΑ͏ʹ conitue Λࢦఆ ʢktlint ͷઃఆͰͦ΋ͦ΋ҟৗऴྃ͠ͳ͍Α͏ʹͯ͠΋Α͍ʣ ಉҰ job ͰಉҰπʔϧͷ݁ՌΛΞοϓϩʔυ͢Δ৔߹͸ category Λ ม͑Δඞཁ͕͋Δʢaction ͕ΤϥʔͱͳΔ ϚϧνϞδϡʔϧߏ੒ͷ৔߹

Slide 26

Slide 26 text

mobsfscan × GitHub code scanning

Slide 27

Slide 27 text

mobsfscan × GitHub code scanning https://github.com/MobSF/mobsfscan

Slide 28

Slide 28 text

mobsfscan is a static analysis tool that can fi nd insecure code patterns in your Android and iOS source code. Supports Java, Kotlin, Android XML, Swift and Objective C Code. mobsfscan uses MobSF static analysis rules and is powered by semgrep and libsast pattern matcher. mobsfscan × GitHub code scanning README Ͱͷઆ໌

Slide 29

Slide 29 text

mobsfscan × GitHub code scanning name: CI on: push: branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: MobSF/mobsfscan@main with: args: . --sarif --output results.sarif continue-on-error: true - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif category: mobsfscan

Slide 30

Slide 30 text

mobsfscan × GitHub code scanning • ݕग़Ͱ͖Δ໰୊͕Ҏ֎ʹগͳ͍ʁ • େ͖ͳϓϩδΣΫτͰ͸ࢼ͍ͤͯͳ͍͕ɺࢼ͠ʹ google/iosched ͷΞ ϓϦΛର৅ʹݕࠪͯ͠΋ 9 ݅ͷݕग़ͩͬͨ • ൺֱͱͯ͠ɺQodana ʹΑΔݕग़͸ 2,800 ݅ • ΋͔ͯ͜͠͠ΕͰ΋े෼ͳݕࠪ͸͞Ε͍ͯΔͷ͔΋͠Εͳ͍͕ɺ಺༰ͷ ਫ਼ࠪ͸ඞཁͦ͏

Slide 31

Slide 31 text

Qodana × GitHub code scanning

Slide 32

Slide 32 text

Qodana × GitHub code scanning https://www.jetbrains.com/ja-jp/qodana Qodana: JetBrains ͷ੩తίʔυղੳπʔϧ

Slide 33

Slide 33 text

Qodana × GitHub code scanning • JVMʢJava / KotlinʣɺAndroid ͸ Community ϓϥϯʢແྉʣͰ΋࢖͑Δ • ଞͷ༗ྉϓϥϯͱͷػೳࠩ͸গ͋͠Δ • Community ϓϥϯ૬౰ͷػೳʢڪΒ͘ʣΛར༻͢ΔݶΓͰ͸ɺ JetBrains ΞΧ΢ϯτͳ͠ʹ GitHub Actions ͷϫʔΫϑϩʔͰར༻Ͱ͖Δ • ϫʔΫϑϩʔͱμογϡϘʔυʢQodana Cloudɻར༻ʹ͸ JetBrains ΞΧ΢ϯτ͕ඞཁʣΛ࿈ܞ͢Δ৔߹͸ɺCloud ଆͰൃߦ͞ΕͨτʔΫϯ ΛϫʔΫϑϩʔ΁ઃఆ͢Δඞཁ͕͋Δ

Slide 34

Slide 34 text

version: "1.0" linter: jetbrains/qodana-jvm-android:2023.3 profile: name: qodana.recommended projectJDK: 17 Qodana × GitHub code scanning ϦϙδτϦ௚Լʹ qodana.yaml ϑΝΠϧΛ഑ஔ

Slide 35

Slide 35 text

Qodana × GitHub code scanning name: CI on: push: branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: JetBrains/qodana-action@v2023.3 with: post-pr-comment: false use-annotations: false pr-mode: false - run: | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android Qodana ͷϓϧϦΫ࿈ܞͷػೳ͸શͯ off ʹʢมߋߦʹର͢Δ annotation ͕ code scanning ͷ΋ͷͱඃΔͷͰʣ

Slide 36

Slide 36 text

Qodana × GitHub code scanning SARIF ϑΝΠϧͷՃ޻͕ඞཁ - run: | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android .runs[].automationDetails ཝΛ࡟আ

Slide 37

Slide 37 text

Qodana × GitHub code scanning ʢલϖʔδͷଓ͖ʣcategory ΁ࢦఆͨ͠จࣈྻΑΓ΋ SARIF ಺ͷ .runs[].automationDetails.id ͷ จࣈྻ͕༏ઌ͞Ε code scanning ΁౉͞ΕΔɻຊདྷ͸ͦΕͰ΋Α͍͕ݱঢ়ɺQodana ͕ੜ੒͢Δ SARIF ϑΝΠϧͰ͸ϓϧϦΫͱ push ΠϕϯτͰ id ͷ಺༰͕ҟͳΔҝɺcode scanning ͷը໘Ͱ ܯࠂ͕දࣔ͞Εͯ͠·͏ Αͬͯࣄલʹ .runs[].automationDetails ཝΛ࡟আ͠ɺϫʔΫϑϩʔͰࢦఆͨ͠ category Λద༻ͤ͞Δ

Slide 38

Slide 38 text

Qodana × GitHub code scanning - uses: JetBrains/qodana-action@v2023.3 env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} with: post-pr-comment: false use-annotations: false pr-mode: false Qodana ͷμογϡϘʔυʢQodana Cloudʣͱ࿈ܞ͢Δ৔߹ Cloud ଆͰൃߦ͞ΕͨτʔΫϯΛઃఆ

Slide 39

Slide 39 text

Qodana × GitHub code scanning Qodana Cloudʢϒϥ΢βͰӾཡʣ

Slide 40

Slide 40 text

Qodana × GitHub code scanning • Android Lint ͱॏෳ͢Δݕ͕ࠪଟ͍͔΋͠Εͳ͍ • ಉ࣌ʹϨϙʔτ͢Δͱ։ൃऀ͕ࠞཚͯ͠͠·͏Մೳੑ • Qodana ͱ Android Lint ͷݕࠪͷΧόʔൣғΛͦΕͧΕ֬ೝͨ͠ํ͕Α ͍͔΋ • ৔߹ʹΑͬͯ͸ Qodana ΁ҰຊԽ͢Δʁ

Slide 41

Slide 41 text

steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: JetBrains/qodana-action@v2023.3 with: post-pr-comment: true use-annotations: true pr-mode: true - run: | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: actions/checkout@v4 - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android σϑΥϧτ஋Ͳ͓ΓͳͷͰࢦఆͳ͠Ͱ΋Α͍ ʢuse-annotation Ҏ֎͸ push ΠϕϯτͰ͸ແࢹ͞ΕΔʣ Qodana × GitHub code scanningʢิ଍ʣ Ծʹ JetBrains/qodana-action ͷ pr-mode Λར༻͢Δ৔߹ɺϫʔΫεϖʔεͷ Git ͷঢ়ଶ͕ม Θͬͯ͠·͍ޙଓͷ github/codeql-action/upload-sarif ͕͏·͘ಈ͔ͳ͘ͳΔͷͰɺ࠶νΣοΫ Ξ΢τ౳Ͱ Git ͷঢ়ଶΛ໭͓ͯ͘͠ඞཁ͕͋Δ ԾʹϓϧϦΫͰ pr-mode Λར༻͢Δ৔߹ 0 ʹ͠ͳ͍ͱ pr-mode ͕ద༻͞Εͳ͍ ·ͨ post-pr-comment ͸ pull-requests: write permission ͕ɺ use-annotations ͸ checks: write permission ͕ඞཁ ͜͜Ͱ࠶νΣοΫΞ΢τ͕ඞཁʂ

Slide 42

Slide 42 text

Qodana × GitHub code scanningʢิ଍ʣ ʢલϖʔδͷଓ͖ʣQodana ʹ͸ GitHub Actions ͷ cache Λར༻ͨ͠Ϧιʔεͷ࠶ར༻ͷ࢓૊Έ ͕͋Δ͕ɺΩϟογϡ͕ແ͍ঢ়ଶͰ JetBrains/qodana-action Λ࢖༻͢Δͱɺͳ͔ͥݕग़݅਺͕ গͳ͘ͳΔݱ৅͕ΈΒΕͨɻকདྷతʹվળ͞ΕΔ͔΋͠Εͳ͍ɻ cache ͸σϑΥϧτͰ͸ϒϥϯνຖʹ࡞੒͞ΕΔɻmain ϒϥϯνͷΑ͏ͳ௕͘ར༻͞ΕΔϒϥϯ νͰ͸աڈͷ cache ͕͋Δҝ΄΅໰୊ͱ͸Βͳ͍͕ɺϓϧϦΫͷ৔߹͸ open ࣌͸ cache ͕ແ͍ ঢ়ଶͱͳͬͯ͠·͏ҝɺຊ action ͷ additional-cache-key ʹʮqodana-2023.3-ʯ౳ͷ cache Ωʔ Λࢦఆͯ͠ɺϚʔδઌͷϒϥϯν ·ͨ͸ σϑΥϧτϒϥϯνͷ cache Λ open ࣌ʹ΋ద༻͞ΕΔ Α͏ʹͨ͠ํ͕Α͍͔΋͠Εͳ͍ɻʢͨͩ cache ͷ෭࡞༻తͳ΋ͷ͸ؾʹͳΔͱ͜Ζ͕ͩɻʣ

Slide 43

Slide 43 text

CodeQL × GitHub code scanning

Slide 44

Slide 44 text

CodeQL × GitHub code scanning name: CI on: push: branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: github/codeql-action/init@v3 with: languages: java-kotlin - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew assembleDebug - uses: github/codeql-action/analyze@v3 with: category: codeql:java-kotlin ͜ͷ action Ͱ SARIF ͷΞοϓϩʔυ·ͰߦΘΕΔ java-kotlin Λࢦఆ

Slide 45

Slide 45 text

CodeQL × GitHub code scanning Android ʹؔ͢Δݕࠪ΋͞ΕΔ

Slide 46

Slide 46 text

CodeQL × GitHub code scanning • ͦ΋ͦ΋ GitHub code scanning ͱ࿈ܞ͢Δ΋ͷͳͷͰ͢ΜͳΓಋೖͰ͖ Δʢ͸ͣʣ • ݕग़Ͱ͖Δ໰୊͕Ҏ֎ʹগͳ͍ʁ • େ͖ͳϓϩδΣΫτͰ͸ࢼ͍ͤͯͳ͍͕ɺࢼ͠ʹ google/iosched ͷΞ ϓϦΛର৅ʹݕࠪͯ͠΋ 1 ݅ͷݕग़ͩͬͨ • ൺֱͱͯ͠ɺQodana ʹΑΔݕग़͸ 2,800 ݅ • ݱ࣌఺Ͱ·ͩ ϕʔλ൛ ͔ͩΒ͔΋ʁ

Slide 47

Slide 47 text

GitHub code scanning Λ࢖Θͳ͍৔߹

Slide 48

Slide 48 text

GitHub code scanning Λ࢖Θͳ͍৔߹ • GitHub code scanning ͸ private ϦϙδτϦͰ͸ GitHub Advanced Security ͷϥΠηϯεʢ༗ྉʣ͕ඞཁ • ۀ຿ͷϓϩδΣΫτ͸େ֓ private ͳͷͰར༻͢Δʹ͸ෑډ͕͋Δ • ݱ࣌఺Ͱ͸ʢࢲͷ؍ଌൣғͰ͸ʣSARIF ϑΝΠϧ͔Βద੾ͳϨϙʔτΛ͠ ͯ͘ΕΔผͷαʔϏε΍πʔϧ౳͸ݟ͔ͭΒͳ͔ͬͨ • ͦ΋ͦ΋ SARIF ϑΝΠϧΛར༻͢Δඞཁ͕͋Δ͔ʁͱ͍͏͜ͱʹ͍ͭͯ ͸ɺ֤੩తղੳπʔϧΛ౷Ұతʹӡ༻͍ͨ͠ͱ͍͏χʔζʹର͢Δڞ௨ ϑΥʔϚοτͱͯ͠ɺ͜ΕΛར༻͢ΔҰఆͷҙٛ͸͋Δʢͱࢥ͏ʣ

Slide 49

Slide 49 text

GitHub code scanning Λ࢖Θͳ͍৔߹ • SARIF ͸ JSON ܗࣜͰ΋͋ͷͰɺ؆୯ʹσʔλΛύʔεͰ͖̎࣍ར༻͠΍ ͍͢ • GitHub Actions ͷϫʔΫϑϩʔͰ͋Ε͹ jq ͕σϑΥϧτͰ࢖͑Δ • JavaScript Ͱ͋Ε͹ͦͷ·· JSON.parse() ͕Մೳ .. ݱ࣌఺Ͱ͸ࣗલͰ SARIF ϑΝΠϧΛύʔεͯ͠ར༻͢ΔΑ͏ͳεΫϦϓτ Λ༻ҙ͢Δͷ͕ྑͦ͞͏

Slide 50

Slide 50 text

GitHub code scanning Λ࢖Θͳ͍৔߹ ͜͜ͰɺCodeQL ʹ͍ͭͯ.. • GitHub code scanning ͕༗ޮͰͳ͍ϦϙδτϦͰ͸ github/codeql- action ܥͷҰ੾ͷ action ͕ΤϥʔͱͳΔ • ͜ΕΒͷ action Λར༻͠ͳ͘ͱ΋ɺCodeQL CLI Λར༻͢Ε͹ SARIF ϑΝΠϧͷग़ྗ·Ͱ͸ग़དྷͦ͏͕ͩɺֶज़ݚڀ౳ͷ໨తͰͳ͍ ৔߹͸ن໿ҧ൓ͱͳͬͯ͠·͏ • ͭ·ΓɺCodeQL ͸ GitHub code scanning ͱηοτͰར༻͢Δඞཁ ͕͋Δ Αͬͯ͜ΕҎ߱ͷ࿩͸ɺCodeQL Ҏ֎ͷ੩తղੳπʔϧͰͷ࿩ͱͳΓ·͢

Slide 51

Slide 51 text

- run: ./gradlew ktlintCheck continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - run: | file='${{ runner.temp }}/ktlint-results.sarif' results="$(cat "$file" | jq -c '.runs[].results[] | { level, location: .locations[0].physicalLocation.artifactLocation.uri, line: .locations[0].physicalLocation.region.startLine, message: .message.text, ruleId }')" IFS=$'\n' for result in $results ; do level="$(echo "$result" | jq -r '.level')" location="$(echo "$result" | jq -r '.location')" line="$(echo "$result" | jq '.line')" message="$(echo "$result" | jq -r '.message')" ruleId="$(echo "$result" | jq -r '.ruleId')" case "$level" in 'error') message_level='error';; 'warning') message_level='warning';; 'note') message_level='notice';; *) # default message_level='warning' esac echo "::${message_level} file=${location},line=${line},title=${ruleId}::${message}" done ktlint ͷ SARIF ͷ಺༰Λ annotation ʹ͢Δྫ ※ ੩తղੳπʔϧʹΑͬͯ͸ level ͸ ruleId ΛΩʔͱͯ͠ rules ཝ౳͔Βऔಘ͢Δඞཁ͕͋Γ·͢ɻ·ͨΤϥʔͷৄࡉ಺ ༰΋ rules ཝ౳͔Βऔಘͨ͠ํ͕ΑΓΑ͍Ͱ͢

Slide 52

Slide 52 text

echo "::${message_level} file=${location},line=${line},title=${ruleId}::${message}" ktlint ͷ SARIF ͷ಺༰Λ annotation ʹ͢Δྫ jq Ͱ߲໨ΛऔΓग़ͯ͠ɺGitHub Actions ͷ work fl ow commands Ͱ annotation ΁

Slide 53

Slide 53 text

ϓϧϦΫͷ Files changed λϒͰͷදࣔ ktlint ͷ SARIF ͷ಺༰Λ annotation ʹ͢Δྫ ※ ຊདྷ͸։ൃऀ͕มߋͨ͠ߦͷΈʹ annotation ͢ΔΑ͏ͳ࣮૷Λͨ͠ํ͕Α͍Ͱ͢ ※ annotation ͷݸ਺ʹ͸੍ݶ͕͋Γ·͢ ※ ·ͨϨϏϡʔίϝϯτͱͯ͠ͷฦ৴΋Ͱ͖ͳ͍ͷͰɺannotation Ͱͳ͘ϓϧϦΫͷίϝϯτʹͨ͠ํ͕Α͍͔΋ Job Summaries Ͱͷදࣔ

Slide 54

Slide 54 text

- run: ./gradlew ktlintCheck continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - run: | { file='${{ runner.temp }}/ktlint-results.sarif' results="$(cat "$file" | jq -c '.runs[].results[] | { level, location: .locations[0].physicalLocation.artifactLocation.uri, line: .locations[0].physicalLocation.region.startLine, message: .message.text, ruleId }')" IFS=$'\n' for result in $results ; do level="$(echo "$result" | jq -r '.level')" location="$(echo "$result" | jq -r '.location')" line="$(echo "$result" | jq '.line')" message="$(echo "$result" | jq -r '.message')" ruleId="$(echo "$result" | jq -r '.ruleId')" case "$level" in 'error') icon=':no_entry_sign:';; 'warning') icon=':warning:';; 'note') icon=':memo:';; *) # default icon=':warning:' esac location_url="https://github.com/${{ github.repository }}/blob/${{ github.sha }}/${location}#L${line}-${line}" echo "- ${icon} line ${line} in [${location}](${location_url})" echo " - **\`${ruleId}\`** ${message}" done } >> "$GITHUB_STEP_SUMMARY" ktlint ͷ SARIF ͷ಺༰Λ Job Summaries ΁ग़ྗ͢Δྫ ϚʔΫμ΢ϯܗࣜͰ Job Summaries ΁ग़ྗ

Slide 55

Slide 55 text

ktlint ͷ SARIF ͷ಺༰Λ Job Summaries ΁ग़ྗ͢Δྫ

Slide 56

Slide 56 text

• CodeQL Λআ͖ɺAndroid LintɺktlintɺmobsfscanɺQodana ͸ SARIF ܗࣜ Ҏ֎ʹ΋ HTML ܗࣜͰͷϨϙʔτग़ྗʹରԠ͍ͯ͠Δ • HTML Λ CI Ͱ GitHub Pages ΁σϓϩΠͯ͠Ӿཡ͢Δ • ීஈ Danger Λར༻͍ͯ͠Δ৔߹͸ danger-sarif ͱ͍͏ϓϥάΠϯ͕͋Δ • https://github.com/irgaly/danger-sarif • Qodana ͸ code scanning ͱ࿈ܞ͠ͳͯ͘΋͜Ε୯ମͰ݁ߏ͔ͭ͑Δ • Android Ͱ͋Ε͹ Community ϓϥϯʢແྉʣͰ࢖͑Δ • μογϡϘʔυʢQodana Cloudʣ࿈ܞ • ϓϧϦΫ࿈ܞʢannotation ΍αϚϦʔͷ౤ߘʣ ͦͷଞͷબ୒ࢶ

Slide 57

Slide 57 text

͓ΘΓʹ

Slide 58

Slide 58 text

͓ΘΓʹ • ·ͣ͸ main ϒϥϯνͷ੩తղੳΛͯ͠Έ༷ͯࢠΛݟΔͷ͕Αͦ͞͏ • ͲͷΑ͏ͳ໰୊͕ݕग़͞ΕΔ͔؍ଌ

Slide 59

Slide 59 text

ͦͷ΄͔ࢀߟ৘ใ

Slide 60

Slide 60 text

ͦͷ΄͔ࢀߟ৘ใ • detekt ΋ SARIF ͱ HTML ܗࣜͰͷϨϙʔτʹରԠ͍ͯ͠Δ • Dart Analyzerʢͱ Flutter AnalyzerʣͷϨϙʔτΛ SARIF ܗࣜ΁ม׵͢Δ GitHub custom action • https://github.com/marketplace/actions/dart-analyzer-sarif • JUnit ͷϨϙʔτΛ GitHub ͷ annotation ʹ͢Δ GitHub custom action • https://github.com/mikepenz/action-junit-report • ʢࠓճͷ SARIF ͷ࿩ͱ͸ؔ܎͋Γ·ͤΜ͕ʣ੩తղੳͱڞʹϓϧϦΫͷ CI ΁ಋ ೖ͢Δͱศརͩͱࢥ͍·͢

Slide 61

Slide 61 text

Thank you ! @hkusu_ ฐࣾ͸ Android ΤϯδχΞΛ ઈࢍืूத Ͱ͢ʂ