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
79 changes: 79 additions & 0 deletions .github/workflows/flutter-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Flutter Test

# Runs the Dart unit/widget suite (test/) on PRs that touch Dart source. Until
# now nothing ran it: every other `flutter test` call in this repo targets
# integration_test/, and all of them sit behind workflow_call (build-linux.yml,
# build-windows.yml) or workflow_dispatch. So no PR-triggered workflow executed
# a single Dart test, and a regression pinned by a unit test could still merge.
#
# That gap is not hypothetical — lantern-box v0.0.101 changed the JSON shape of
# `user_failures` and broke Dart deserialization for every user with a recorded
# failure (#8929). The fix ships with tests, but on `pull_request` nothing would
# have run them.
#
# No Go toolchain, Android SDK, or Java here: `flutter test` runs on the Dart VM
# and builds no platform artifact, which keeps this gate to a couple of minutes.

on:
workflow_dispatch:
pull_request:
paths:
- "lib/**"
- "test/**"
- "pubspec.yaml"
- "pubspec.lock"
- ".github/flutter-version.yaml"
# keep the self-trigger so edits to this workflow re-run it
- ".github/workflows/flutter-test.yml"

concurrency:
group: flutter-test-${{ github.ref }}
cancel-in-progress: true

jobs:
flutter-test:
permissions:
contents: "read"
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
Comment on lines +39 to +40

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
if [ -f .github/workflows/flutter-test.yml ]; then
  nl -ba .github/workflows/flutter-test.yml | sed -n '1,120p'
else
  echo "missing .github/workflows/flutter-test.yml"
fi

echo
echo "== actions checkout usages with persist-credentials =="
rg -n "actions/checkout|persist-credentials" .github/workflows || true

echo
echo "== read commands after checkout that are likely PR-controlled =="
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/flutter-test.yml')
if not p.exists():
    raise SystemExit
lines = p.read_text().splitlines()
for i,l in enumerate(lines,1):
    if i <= 45: continue
    if any(s in l for s in ['shell:', 'run:', '- ', '&&', ';']):
        print(f"{i}: {l}")
PY

Repository: getlantern/lantern

Length of output: 219


🏁 Script executed:

#!/bin/sh
set -euo pipefail

echo "== workflow excerpt =="
if [ -f .github/workflows/flutter-test.yml ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/flutter-test.yml | sed -n '1,140p'
else
  echo "missing .github/workflows/flutter-test.yml"
fi

echo
echo "== actions checkout usages with persist-credentials =="
grep -Rn "actions/checkout\|persist-credentials" .github/workflows || true

echo
echo "== commands after checkout that are likely PR-controlled =="
python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/flutter-test.yml')
if not p.exists():
    raise SystemExit
lines = p.read_text().splitlines()
in_run = False
for i,l in enumerate(lines, 1):
    stripped = l.strip()
    if stripped.startswith('run:'):
        in_run = True
    elif l.startswith('      - ') or l.startswith('    - '):
        in_run = False
    if i <= 45:
        continue
    if in_run or stripped.startswith('make ') or stripped.startswith('flutter ') or stripped.startswith('//'):
        print(f"{i}: {l}")
PY

Repository: getlantern/lantern

Length of output: 6010


🌐 Web query:

actions/checkout v4 persist-credentials default true README

💡 Result:

In actions/checkout version 4, the persist-credentials input defaults to true [1][2]. When this setting is enabled (the default), the authentication token or SSH key used by the action is persisted in the local git configuration [3][4]. This allows subsequent steps in your workflow to execute authenticated git commands [3][4]. The action automatically removes this token during the post-job cleanup phase [3][4]. If you wish to prevent the action from configuring your credentials in the local git config, you can explicitly set persist-credentials to false in your workflow file [3][4].

Citations:


Disable checkout credential persistence before running PR-controlled code.

actions/checkout@v4 persists GITHUB_TOKEN credentials by default, and this pull_request job later runs PR-controlled make pubget, make gen, and flutter test. Set persist-credentials: false unless this workflow needs authenticated Git access.

Proposed fix
       - name: Checkout code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 39-40: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/flutter-test.yml around lines 39 - 40, Update the
actions/checkout@v4 step in the workflow to disable credential persistence by
setting persist-credentials to false before the PR-controlled make pubget, make
gen, and flutter test steps; do not add authenticated Git access unless
explicitly required.

Source: Linters/SAST tools


- name: Cache Flutter dependencies
uses: actions/cache@v4
timeout-minutes: 5
continue-on-error: true
with:
path: |
~/.pub-cache
key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-flutter-

- name: Install Flutter
uses: subosito/flutter-action@v2.22.0
with:
channel: stable
flutter-version-file: .github/flutter-version.yaml
cache: true

# Generated sources are committed, but regenerating means the suite tests
# the PR's own source rather than whatever .g.dart happened to be checked
# in — a model change with a forgotten `make gen` would otherwise pass
# against stale generated code.
- name: Flutter pub get + codegen
run: |
make pubget
make gen

# app.env is a declared pubspec asset, normally decoded from a secret by
# the release workflow. Asset bundling runs before the tests do and fails
# outright if the file is absent, so an empty placeholder is enough — the
# suite reads nothing from it. Same treatment as android-compile-check.yml.
- name: Create placeholder app.env
run: touch app.env

# Reporter is left unset: the Dart test runner defaults to its `github`
# reporter under Actions, which annotates failures inline on the PR.
- name: Run Flutter tests
run: flutter test
28 changes: 0 additions & 28 deletions test/widget_test.dart

This file was deleted.

Loading