Skip to content
Draft
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
99 changes: 99 additions & 0 deletions Dockerfile.debug_test
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright 2022 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

FROM debian:trixie-slim

# Install Dependencies.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
curl \
dnsutils \
git \
openssh-client \
unzip \
gpg \
jq \
procps \
nodejs \
npm \
; \
rm -rf /var/lib/apt/lists/*

# Create the `flutter` user and group.
RUN groupadd -r flutter && useradd -r -g flutter flutter

# Create folders for home / flutter / test.

ENV FLUTTER_ROOT="/opt/flutter"
ENV TEST_ANALYZER="/opt/testanalyzer"

RUN mkdir -p /home/flutter && \
chown -R flutter:flutter /home/flutter

RUN mkdir -p "${FLUTTER_ROOT}" && \
chown -R flutter:flutter "${FLUTTER_ROOT}"

RUN mkdir -p "${TEST_ANALYZER}" && \
chown -R flutter:flutter "${TEST_ANALYZER}"

# Switch users for the rest of the file.
USER flutter

# Clone flutter repository and set up the environment.
RUN git clone https://github.com/flutter/flutter "${FLUTTER_ROOT}"
ENV PATH="${FLUTTER_ROOT}/bin:${PATH}"

WORKDIR "$FLUTTER_ROOT"

# Disable analytics and crash reporting, disable all the other platforms except web.
RUN flutter config \
--no-analytics \
--enable-web \
--no-enable-linux-desktop \
--no-enable-macos-desktop \
--no-enable-windows-desktop \
--no-enable-android \
--no-enable-ios \
--no-enable-fuchsia

# Only download the websdk
RUN flutter precache --web

# Perform a doctor run.
RUN flutter doctor -v

# Install Gemini CLI in the flutter home directory and update path.
WORKDIR /home/flutter
ENV PATH="/home/flutter/node_modules/.bin:$PATH"
RUN npm install @google/gemini-cli
RUN gemini extensions install --consent https://github.com/gemini-cli-extensions/flutter

# Pre-setup Gemini to use API key authentication
RUN <<EOF cat > /home/flutter/.gemini/settings.json
{
"security": {
"auth": {
"selectedType": "gemini-api-key"
}
}
}
EOF

# Copy the testanalyzer script
WORKDIR "${TEST_ANALYZER}"
COPY --chown=flutter:flutter packages/testanalyzer .

# Make entrypoint script executable
RUN chmod +x "${TEST_ANALYZER}/bin/entrypoint.sh"

# Set up environment variables placeholders
ENV GEMINI_API_KEY=""
ENV FAILING_TEST=""
ENV BUILD_NUMBER=""
ENV PR_NUMBER=""
ENV TEST_ENV="try"

ENTRYPOINT [ "/opt/testanalyzer/bin/entrypoint.sh" ]
54 changes: 54 additions & 0 deletions packages/testanalyzer/TEST_PROMPT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Dart Log Failure Parser

You are a helpful assistant that analyzes test failures on Flutter's infrastructure and provides helpful diagnostics and fixes. The failing test logs are provided after the `## Log Content` header.

You are in a stand-alone checkout of the pull request. `dart` and `flutter` tools are in your PATH already. You can find the merge-base with `master` by running `git merge-base master HEAD`. You should use this diff to determine if the failures are related to the code changes in the pull request.

You are in a linux docker container. You can `find` files with either `find . -name '<FILE_NAME_PATTERN>` or `git ls-files | grep <FILE_NAME_PATTERN>`. You can grep for strings or symbols with `git grep <STRING>`.

## Workflow

### 1. Analyze Raw Log Output

Analyze the raw log output for failure details. Do not skim the output; check the entire log. **The description of findings should include specific details for the failures (e.g., unformatted files, specific test names), not just the top-level command that failed.**

### 2. Look for Failure Patterns

#### Pattern A: Error Blocks (e.g., Linux Analyze)
Search for blocks starting with `╡ERROR #`.
Example:
```
╔═╡ERROR #1╞════════════════════════════════════════════════════════════════════
║ Command: bin/cache/dart-sdk/bin/dart --enable-asserts /b/s/w/ir/x/w/flutter/dev/bots/analyze_snippet_code.dart --verbose
║ Command exited with exit code 255 but expected zero exit code.
║ Working directory: /b/s/w/ir/x/w/flutter
╚═══════════════════════════════════════════════════════════════════════════════
```

#### Pattern B: Task Result JSON
Search for "Task result:" followed by a JSON object.
Example:
```json
Task result:
{
"success": false,
"reason": "Task failed: PathNotFoundException: Cannot open file..."
}
```

#### Pattern C: Failing Tests List
For general Dart tests, look for a list at the end of the log starting with "Failing tests:".
Example:
```
Failing tests:
test/general.shard/cache_test.dart: FontSubset artifacts for all platforms on arm64 hosts
test/general.shard/cache_test.dart: FontSubset artifacts on arm64 linux
```

#### Pattern D: Build Failures
For build failures (e.g., engine tests failing at compile time), look for the following indicators in the logs or API summaries:
- Lines starting with `FAILED:` (indicates a Ninja target failed).
- Compiler error messages (e.g., `error:`, `fatal error:`).
- Linker error messages (e.g., `undefined reference to`).
- Summary messages in the check-runs API output like `1 build failed: [<build_name>]`.
`
49 changes: 49 additions & 0 deletions packages/testanalyzer/bin/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/bash
# Copyright 2026 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

set -e

if [ -n "$PR_NUMBER" ]; then
echo "Creating worktree for PR $PR_NUMBER..."
cd "$FLUTTER_ROOT"

# Ensure safe directory
git config --global --add safe.directory "$FLUTTER_ROOT"

# Cleanup
git worktree remove -f pr_review 2>/dev/null || true
git worktree prune || true

# Add worktree in detached state to avoid creating a branch
git worktree add pr_review

cd pr_review

echo "Checking out PR $PR_NUMBER in worktree..."
git fetch origin pull/$PR_NUMBER/head:pr-$PR_NUMBER
git checkout pr-$PR_NUMBER

echo "Running testanalyzer..."
unset PR_NUMBER
# Run the script from the worktree directory
dart /opt/testanalyzer/bin/testanalyzer.dart

if [ -f "failure_log.txt" ]; then
echo "Analyzing log with Gemini..."

echo "Constructing prompt..."
echo "Analyze the following log failures based on the provided skill." > prompt.txt
echo "" >> prompt.txt
echo "### Skill Definition" >> prompt.txt
cat /opt/testanalyzer/TEST_PROMPT.md >> prompt.txt
echo "" >> prompt.txt
echo "## Log Content" >> prompt.txt
cat failure_log.txt >> prompt.txt

gemini --skip-trust --yolo -p "Please read the following instructions and execute them: @prompt.txt"
else
echo "Failure log not found. Analysis skipped."
fi
fi
Loading
Loading