Skip to content
Open
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
45 changes: 45 additions & 0 deletions .github/workflows/actionlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: actionlint

on:
push:
branches: [main]
paths:
- ".github/workflows/**"
- ".github/actions/**"
- ".github/actionlint*"
pull_request:
paths:
- ".github/workflows/**"
- ".github/actions/**"
- ".github/actionlint*"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: actionlint-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
actionlint:
name: Lint workflow YAML
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

# Run actionlint via the official downloader script. Runs the binary
# directly on the checkout, no third-party action needed. Includes
# shellcheck for `run:` blocks and pyflakes for python in `run:` blocks.
- name: Download actionlint
id: get_actionlint
run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/011a6d15e749bb3f2d771eed9c7aa0e7e3e10ee7/scripts/download-actionlint.bash)
shell: bash

- name: Run actionlint
run: ${{ steps.get_actionlint.outputs.executable }} -color
shell: bash
97 changes: 91 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@ concurrency:
env:
FLUTTER_VERSION: "3.41.5"
FLUTTER_CHANNEL: stable
# subosito/flutter-action@v2 — pinned to commit SHA for supply-chain safety.
# Bump in lockstep with the Dependabot github-actions update PR.
FLUTTER_ACTION_REF: 1a449444c387b1966244ae4d4f8c696479add0b2
Comment on lines +20 to +22

jobs:
analyze:
name: Analyze + Format
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: ${{ env.FLUTTER_CHANNEL }}
Expand All @@ -41,10 +48,14 @@ jobs:
test:
name: Unit + Widget tests
runs-on: ubuntu-latest
timeout-minutes: 20
needs: analyze
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: ${{ env.FLUTTER_CHANNEL }}
Expand All @@ -60,18 +71,23 @@ jobs:
name: coverage-lcov
path: coverage/lcov.info
if-no-files-found: ignore
retention-days: 30

build-android:
name: Build Android (debug APK)
runs-on: ubuntu-latest
timeout-minutes: 30
needs: test
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- uses: subosito/flutter-action@v2
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: ${{ env.FLUTTER_CHANNEL }}
Expand All @@ -87,13 +103,50 @@ jobs:
if-no-files-found: error
retention-days: 14

# iOS build is informational, not gating. Reasons:
# 1. Tyler's dev machine is Windows; iOS validation happens on a Mac
# pre-store-submission, not on every PR.
# 2. Transitive deps (currently device_info_plus 12.4.0) periodically
# ship code that requires a newer Xcode SDK than the macOS runner
# ships, breaking unrelated PRs.
# 3. macos-latest runner minutes are 10x ubuntu-latest — not worth
# burning on PRs that touch no iOS files.
# Path-filtered to iOS-relevant files; does not gate test/analyze.
changed:
name: Detect changed paths
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
ios: ${{ steps.filter.outputs.ios }}
steps:
- uses: actions/checkout@v4
- id: filter
# dorny/paths-filter@v3 — pinned to commit SHA. Reads its filter
# config from the workflow file directly via the `filters:` input.
uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590
with:
filters: |
ios:
- 'ios/**'
- 'pubspec.yaml'
- 'pubspec.lock'
- '.github/workflows/ci.yml'

build-ios:
name: Build iOS (no codesign)
runs-on: macos-latest
needs: test
timeout-minutes: 45
needs: [test, changed]
if: needs.changed.outputs.ios == 'true'
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: ${{ env.FLUTTER_CHANNEL }}
Expand All @@ -106,10 +159,14 @@ jobs:
build-web:
name: Build Web
runs-on: ubuntu-latest
timeout-minutes: 20
needs: test
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: ${{ env.FLUTTER_CHANNEL }}
Expand All @@ -123,3 +180,31 @@ jobs:
path: build/web
if-no-files-found: error
retention-days: 14

coverage-comment:
name: Coverage PR comment
runs-on: ubuntu-latest
timeout-minutes: 5
needs: test
if: github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Download coverage
uses: actions/download-artifact@v4
with:
name: coverage-lcov
path: coverage
# romeovs/lcov-reporter-action — pinned to commit SHA. Posts a sticky PR
# comment with line / branch coverage diff vs the PR base. Soft signal —
# does not gate the merge. Use branch-protection rulesets to make the
# `test` job a required check; this is just visibility.
- name: Post coverage comment
if: hashFiles('coverage/lcov.info') != ''
uses: romeovs/lcov-reporter-action@25674467b99fc58cc7706dc246d9647a94b5ba8f
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lcov-file: coverage/lcov.info
delete-old-comments: true
71 changes: 71 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: CodeQL

on:
push:
branches: [main]
paths:
- "android/**/*.java"
- "android/**/*.kt"
- "ios/**/*.swift"
- ".github/workflows/codeql.yml"
pull_request:
branches: [main]
paths:
- "android/**/*.java"
- "android/**/*.kt"
- "ios/**/*.swift"
- ".github/workflows/codeql.yml"
schedule:
- cron: '0 9 * * 1'

permissions:
contents: read

concurrency:
group: codeql-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: CodeQL (${{ matrix.language }})
# CodeQL is free for public repos. On private repos it requires GitHub
# Advanced Security (paid). Skip until the repo is public OR GHAS is
# enabled — otherwise runs would fail with `Resource not accessible by
# integration` on every PR.
if: github.event.repository.visibility == 'public'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
security-events: write
packages: read
actions: read
contents: read

strategy:
fail-fast: false
matrix:
include:
- language: java-kotlin
build-mode: none
- language: swift
build-mode: manual

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
queries: security-extended,security-and-quality

- name: Autobuild (Swift)
if: matrix.language == 'swift'
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
9 changes: 8 additions & 1 deletion .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ on:

permissions:
contents: read
pull-requests: read

concurrency:
group: commitlint-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
commitlint:
name: Lint commit messages
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v4
with:
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/osv-scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: OSV-Scanner

on:
push:
branches: [main]
pull_request:
branches: [main]
paths:
- "pubspec.yaml"
- "pubspec.lock"
- "android/build.gradle*"
- "android/app/build.gradle*"
- "android/settings.gradle*"
- ".github/workflows/osv-scanner.yml"
schedule:
- cron: '0 7 * * 1'

permissions:
contents: read

concurrency:
group: osv-scanner-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
scan:
name: OSV-Scanner (pubspec + gradle)
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v4

# google/osv-scanner-action/osv-scanner-action — pinned to commit SHA.
# Scans pubspec.lock, gradle build files, and any other supported manifest
# in the tree against the OSV.dev vulnerability database. Free, no API key
# required, works on private repos without GHAS.
- name: Run OSV-Scanner
uses: google/osv-scanner-action/osv-scanner-action@43f380b8fc43a816831a9f5ee6fc91170809c7e9
with:
scan-args: |-
--recursive
--skip-git
--format=sarif
--output=osv-results.sarif
./
continue-on-error: true

- name: Upload SARIF
if: always() && hashFiles('osv-results.sarif') != ''
uses: actions/upload-artifact@v4
with:
name: osv-scanner-sarif
path: osv-results.sarif
if-no-files-found: ignore
retention-days: 30
Loading
Loading