Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/scripts/create-ci-config.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,27 @@ test("keeps pull request validation secretless and release credentials isolated"
assert.match(releaseWorkflow, new RegExp(`secrets\\.${secretName}`));
}
});

test("keeps the required managed-device check attached to same-repository pull request heads", async () => {
const source = await readFile(
join(githubDirectory, "workflows", "android-managed-device.yml"),
"utf8",
);

assert.match(
source,
/^\s{2}pull_request:\n\s{4}types:\s*\[opened,\s*reopened,\s*synchronize\]$/m,
);
assert.match(source, /^\s{4}name:\s*Pixel 2 API 30 androidTest$/m);
assert.match(
source,
/github\.event_name != 'pull_request'\s*\|\|\s*github\.event\.pull_request\.head\.repo\.full_name == github\.repository/,
);
assert.match(
source,
/ref:\s*\$\{\{\s*github\.event_name == 'pull_request' && github\.event\.pull_request\.head\.sha \|\| github\.sha\s*\}\}/,
);
assert.match(source, /persist-credentials:\s*false/);
assert.match(source, /actual_sha="\$\(git rev-parse HEAD\)"/);
assert.match(source, /"\$actual_sha" != "\$EXPECTED_SHA"/);
});
50 changes: 40 additions & 10 deletions .github/workflows/android-managed-device.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,50 @@
name: Android Managed Device Test

# PR 필수 검증으로 올리기 전 안정화 단계다. 수동 실행과 정기 실행의 최근 3회가 연속
# 성공했는지는 별도 gate 이슈에서 판단하며, 실패를 감추는 job/test 재시도는 두지 않는다.
# main PR 의 필수 API 30 검증이다. same-repository PR 을 pull_request 권한 경계에서
# 직접 실행하고 정확한 head SHA 를 검사한다. fork PR 은 신뢰 경계상 자동 실행하지 않는다.
# 수동·정기 실행은 event SHA 를 사용하며, 실패를 감추는 job/test 재시도는 두지 않는다.
on:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
schedule:
- cron: "17 18 * * 2,5"

permissions:
contents: read

concurrency:
group: android-managed-device-${{ github.ref }}
cancel-in-progress: false
group: android-managed-device-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
managed-device:
if: >-
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
name: Pixel 2 API 30 androidTest
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
persist-credentials: false

- name: Verify checked out revision
env:
EXPECTED_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
run: |
set -euo pipefail
actual_sha="$(git rev-parse HEAD)"
if [[ "$actual_sha" != "$EXPECTED_SHA" ]]; then
echo "::error::checkout $actual_sha 가 기대한 revision $EXPECTED_SHA 와 다릅니다"
exit 1
fi

- name: Set up JDK
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: temurin
java-version: "21"
Expand All @@ -36,12 +56,22 @@ jobs:
cache-read-only: true
validate-wrappers: true

- name: Enable KVM access
- name: Enable and verify KVM access
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0660", OPTIONS+="static_node=kvm"' \
runner_user="$(id -un)"
echo "KERNEL==\"kvm\", OWNER=\"${runner_user}\", GROUP=\"kvm\", MODE=\"0660\", OPTIONS+=\"static_node=kvm\"" \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
sudo udevadm trigger --name-match=kvm --settle

id
ls -l /dev/kvm
if [[ ! -c /dev/kvm || ! -r /dev/kvm || ! -w /dev/kvm ]]; then
echo "::error::/dev/kvm must be a character device readable and writable by the runner"
exit 1
fi
"${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" "emulator"
"${ANDROID_HOME}/emulator/emulator" -accel-check

- name: Set up CI-only app configuration
uses: ./.github/actions/setup-ci-config
Expand All @@ -54,7 +84,7 @@ jobs:

- name: Upload androidTest reports and failure evidence
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: android-managed-device-results-${{ github.run_attempt }}
if-no-files-found: warn
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/auto-close-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Close issues referenced by close keywords
uses: actions/github-script@v9
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const pr = context.payload.pull_request;
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/conflict-label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/dependency-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ jobs:
REPORT_DIR: build/reports/dependency-audit
steps:
- name: Clone default branch
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:

- name: Upload machine-readable audit evidence
if: always()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: android-dependency-audit
path: ${{ env.REPORT_DIR }}
Expand Down
13 changes: 9 additions & 4 deletions .github/workflows/dependency-submission.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
name: Gradle Dependency Submission

# develop push 는 신뢰된 base snapshot 을 직접 제출한다. PR 은 fork 를 포함해 write token 없이
# develop·main push 는 신뢰된 base snapshot 을 직접 제출한다. PR 은 fork 를 포함해 write token 없이
# snapshot artifact 만 만들고, default branch 의 별도 workflow_run 이 이를 제출한다.
#
# main 이 함께 있어야 하는 이유 — dependency-review 는 PR 의 base ref 스냅샷과 head 스냅샷을
# 짝지어 «추가된 의존성» 을 계산한다. develop 만 제출하면 릴리스 PR(develop → main)의 base 가
# 빈 것으로 보여 의존성 전량이 신규 도입으로 잡히고, 그 안에 섞인 기존 취약점이 릴리스 PR
# 탓으로 걸린다 (#1063).
on:
push:
branches: [develop]
branches: [develop, main]
pull_request:

concurrency:
Expand All @@ -15,9 +20,9 @@ permissions:
contents: read

jobs:
submit-default-branch:
submit-trusted-branch:
if: github.event_name == 'push'
name: Submit trusted develop dependency graph
name: Submit trusted branch dependency graph
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/deployment-decision.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone merged revision
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.merge_commit_sha || 'develop' }}
fetch-depth: 0
Expand All @@ -50,7 +50,7 @@ jobs:
"$DEPLOYMENT_DECISION_PATH"

- name: Publish decision on the merged PR
uses: actions/github-script@v9
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
DEPLOYMENT_DECISION_PATH: ${{ runner.temp }}/afternote-deployment-decision/decision.json
TARGET_PR_NUMBER: ${{ github.event.pull_request.number || inputs.pull_request_number }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/firebase-wif-canary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
steps:
# google-github-actions/auth가 ADC 파일을 안전하게 만들려면 checkout이 먼저 실행돼야 한다.
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Prepare Firebase release notes
env:
Expand All @@ -81,7 +81,7 @@ jobs:
cat "$RELEASE_NOTES_FILE" >> "$GITHUB_STEP_SUMMARY"

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: temurin
java-version: '21'
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down Expand Up @@ -59,10 +59,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down Expand Up @@ -103,7 +103,7 @@ jobs:

- name: Report Android Lint (Reviewdog)
if: always()
uses: dvdandroid/action-android-lint@master
uses: dvdandroid/action-android-lint@21c9fa6500c10caa12d8c581d9e280925f39510d # v1.3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mock-cleanup-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Check for MOCK_CLEANUP markers
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-distribution.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
esac

- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Load release metadata from main PR
if: github.event_name == 'push'
Expand Down Expand Up @@ -81,7 +81,7 @@ jobs:
cat "$RELEASE_NOTES_FILE" >> "$GITHUB_STEP_SUMMARY"

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: 'temurin'
java-version: '21'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/repository-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
timeout-minutes: 3
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install actionlint
env:
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/screenshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# docker buildx + gha cache 로 Dockerfile.screenshot 빌드.
# 동일 이미지에서 baseline 생성·검증을 수행해 anti-aliasing/font/scale 등 host 환경 차이 root fix.
# Dockerfile 변경 없으면 cache 재사용 — 분당 단위 추가 비용.
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0

- name: Build screenshot image
uses: docker/build-push-action@v7
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
file: Dockerfile.screenshot
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:
# 실패 시 diff/rendered 이미지를 artifact 로 업로드 — 본인이 다운로드해 시각 차이 확인 가능
- name: Upload screenshot diff on failure
if: failure()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: screenshot-test-results
path: |
Expand All @@ -90,7 +90,7 @@ jobs:
# 같은 PR 의 재실행에서는 기존 코멘트를 update (marker 로 중복 누적 방지).
- name: Comment artifact URL on PR (failure)
if: failure() && github.event_name == 'pull_request'
uses: actions/github-script@v9
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const marker = '<!-- screenshot-fail-bot -->';
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Unit Test
# - :koverXmlReportCi / :koverHtmlReportCi : Android debug + 순수 JVM 테스트와 aggregate coverage
# - :konsist:test : 순수 JVM 모듈(testDebugUnitTest 미보유)이라 별도 명시. 레이어 의존 아키텍처 가드.
# - :build-logic:test : included build 라 루트 태스크에 안 묶여 별도 명시. release 키 가드(TestKit) 회귀 가드.
# - :app:compileDebugAndroidTestKotlin : androidTest 소스셋 컴파일 가드. GMD 스위트는 PR 트리거 없이
# 화·금 스케줄로만 돌아(android-managed-device.yml), main 코드 변경이 androidTest 를 깨뜨려도
# 머지 전 어디서도 검출되지 않았다(#936 — develop 컴파일 실패 44건). 에뮬레이터 없이 컴파일만 검증.
# - :app:compileDebugAndroidTestKotlin : androidTest 소스셋 컴파일 가드. GMD API 30은 same-repository
# PR 과 화·금 스케줄에서 실행한다. fork PR 도 에뮬레이터 없이 컴파일은 항상 검증한다
# (#936 — develop 컴파일 실패 44건).
# lint.yml 과 setup 이 거의 동일하지만 분리 — lint 실패가 test 결과를 가리지 않도록 fail-fast 독립.

# base 필터를 두지 않는다 — base 변경(feat/* → develop)은 pull_request 기본 activity type 에
Expand All @@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v7
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Fetch pull request history for changed-module coverage
env:
Expand All @@ -43,7 +43,7 @@ jobs:
run: node --test .github/scripts/*.test.mjs

- name: Set up JDK 21
uses: actions/setup-java@v5
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0
with:
distribution: 'temurin'
java-version: '21'
Expand All @@ -63,7 +63,7 @@ jobs:

- name: Upload Kover coverage reports
id: kover-artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: kover-jvm-coverage
path: build/reports/kover/
Expand All @@ -80,7 +80,7 @@ jobs:
# 실패한 테스트의 HTML/XML 리포트를 PR artifact 로 보존 — CI 로그에서 stack trace 추적이 빠름.
- name: Upload test reports on failure
if: failure()
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: unit-test-reports
path: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,9 @@ class ReceiverRuntimeCompletionAndroidTest {
.assertIsDisplayed()

assertEquals(2, reporter.failures.size)
assertEquals("receiver_home_load", reporter.failures[0].second["home_stage"])
assertEquals("receiver_home_partial_load", reporter.failures[1].second["home_stage"])
assertEquals("mind_records", reporter.failures[1].second["home_failed_sources"])
assertEquals("receiver_home_load", reporter.failures[0].second["receiver_stage"])
assertEquals("receiver_home_partial_load", reporter.failures[1].second["receiver_stage"])
assertEquals("mind_records", reporter.failures[1].second["receiver_failed_sources"])
assertEquals(listOf(2, 2, 2, 2), homeCallCounts())
}

Expand Down
Loading
Loading