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
147 changes: 147 additions & 0 deletions .github/workflows/screenshots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
name: PR Screenshots

on:
pull_request:
types: [opened, synchronize]

jobs:
screenshots:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Skip if last commit is a screenshot update
id: check
uses: actions/github-script@v7
with:
script: |
const commits = await github.rest.pulls.listCommits({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
per_page: 1,
});
const lastMsg = commits.data.at(-1)?.commit?.message ?? '';
core.setOutput('skip', lastMsg.includes('[screenshots]') ? 'true' : 'false');

- name: Checkout PR branch
if: steps.check.outputs.skip != 'true'
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up JDK 17
if: steps.check.outputs.skip != 'true'
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Cache Gradle
if: steps.check.outputs.skip != 'true'
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: gradle-${{ runner.os }}-

- name: Create local.properties
if: steps.check.outputs.skip != 'true'
run: echo "sdk.dir=$ANDROID_HOME" > local.properties

- name: Generate screenshots
if: steps.check.outputs.skip != 'true'
run: ./gradlew :app:updateDebugScreenshotTest --no-daemon

- name: Commit screenshots to PR branch
if: steps.check.outputs.skip != 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

SCREENSHOT_DIR="app/src/screenshotTestDebug/reference"
if [ ! -d "$SCREENSHOT_DIR" ]; then
echo "No screenshot directory found, skipping."
exit 0
fi

git add "$SCREENSHOT_DIR"
if git diff --cached --quiet; then
echo "No screenshot changes to commit."
else
git commit -m "[screenshots] Update preview screenshots"
git push
fi

- name: Post screenshots as PR comment
if: steps.check.outputs.skip != 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const screenshotDir = 'app/src/screenshotTestDebug/reference';

if (!fs.existsSync(screenshotDir)) {
core.info('No screenshot directory found, skipping comment.');
return;
}

const files = fs.readdirSync(screenshotDir).filter(f => f.endsWith('.png'));
if (files.length === 0) {
core.info('No screenshots found, skipping comment.');
return;
}

const branch = context.payload.pull_request.head.ref;
const repo = `${context.repo.owner}/${context.repo.repo}`;

let body = '## App Screenshots\n\n';
body += 'Auto-generated preview screenshots for this PR:\n\n';
body += '<table>\n';

for (let i = 0; i < files.length; i++) {
const file = files[i];
// Extract a readable name from the filename
const name = file
.replace(/^com\.example\.myapplication\./, '')
.replace(/_[a-f0-9]+_[a-f0-9]+_\d+\.png$/, '')
.replace(/([A-Z])/g, ' $1')
.trim();

const url = `https://raw.githubusercontent.com/${repo}/${branch}/${screenshotDir}/${file}`;

if (i % 2 === 0) body += '<tr>\n';
body += `<td align="center"><strong>${name}</strong><br/><img src="${url}" width="350"/></td>\n`;
if (i % 2 === 1 || i === files.length - 1) body += '</tr>\n';
}

body += '</table>\n';

// Delete previous screenshot comments to avoid clutter
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
});
for (const comment of comments.data) {
if (comment.body?.startsWith('## App Screenshots')) {
await github.rest.issues.deleteComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: comment.id,
});
}
}

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: body,
});
4 changes: 4 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.secrets)
alias(libs.plugins.screenshot)
}

android {
Expand Down Expand Up @@ -36,6 +37,7 @@ android {
compose = true
buildConfig = true
}
experimentalProperties["android.experimental.enableScreenshotTest"] = true
}

dependencies {
Expand All @@ -61,4 +63,6 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest)
screenshotTestImplementation(libs.screenshot.validation.api)
screenshotTestImplementation(libs.androidx.compose.ui.tooling)
}
Loading
Loading