diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf22cb091d..538182a09f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,7 @@ permissions: jobs: check: + name: "analyze, test, generate" runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 @@ -14,6 +15,24 @@ jobs: - name: Install system dependencies run: TERM=dumb sudo apt install libsqlite3-dev -y + - name: Clone Flutter SDK + run: tools/ci/clone-flutter-sdk + + - name: Download Flutter SDK artifacts (flutter precache) + run: flutter precache --universal + + - name: Download our dependencies (flutter pub get) + run: flutter pub get + + - name: Run tools/check + run: TERM=dumb tools/check --no-pub --all --output ci --exclude android + + android: + name: "Android build and lint" + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Set up JDK uses: actions/setup-java@v5 with: @@ -30,4 +49,4 @@ jobs: run: flutter pub get - name: Run tools/check - run: TERM=dumb tools/check --no-pub --all --output ci + run: TERM=dumb tools/check --all --output ci android diff --git a/tools/check b/tools/check index 8cfe5ff603..ab8db38140 100755 --- a/tools/check +++ b/tools/check @@ -65,6 +65,9 @@ What tests to run: \`git help revisions\` for many more ways to name a commit.) --all In the given suites, run on all files. If no list of suites was specified, run all suites. + --exclude SUITE + Don't run the given suite, despite \`--all\` + or the suite appearing as a positional argument. Extra things to do, or skip doing: --fix Fix issues found, where possible. @@ -82,10 +85,27 @@ EOF exit 2 } +all_suites=( "${default_suites[@]}" "${extra_suites[@]}" ) + +# usage: is_suite PUTATIVE_SUITE +# +# Succeeds just if the given argument is the name of a suite. +is_suite() { + needle="$1" + # This logic relies on the fact that the suite names have no spaces. + + ! [[ "${needle}" =~ " " ]] \ + || return + + # shellcheck disable=SC2076 # matching literally is the point + [[ " ${all_suites[*]} " =~ " ${needle} " ]] +} + orig_cmdline="$0 $*" opt_files=branch opt_all= +opt_exclude=() opt_fix= opt_no_pub= opt_output=default @@ -95,13 +115,14 @@ while (( $# )); do --diff) shift; opt_files=diff:"$1"; shift;; --all-files) opt_files=all; shift;; --all) opt_files=all; opt_all=1; shift;; + --exclude) shift; if ! is_suite "$1"; then usage; else + opt_exclude+=("$1"); shift; fi;; --fix) opt_fix=1; shift;; --no-pub) opt_no_pub=1; shift;; --output) shift; opt_output="$1"; shift;; --verbose) opt_output=verbose; shift;; - analyze|test|flutter_version|build_runner|l10n|drift|pigeon|icons|android|shellcheck) - opt_suites+=("$1"); shift;; - *) usage;; + *) if ! is_suite "$1"; then usage; else + opt_suites+=("$1"); shift; fi;; esac done @@ -115,12 +136,23 @@ esac if (( ! "${#opt_suites[@]}" )); then if [ -n "${opt_all}" ]; then - opt_suites=( "${default_suites[@]}" "${extra_suites[@]}" ) + opt_suites=( "${all_suites[@]}" ) else opt_suites=( "${default_suites[@]}" ) fi fi +if (( "${#opt_exclude[@]}" )); then + # This logic relies on suite names having no spaces nor glob characters. + suites_str=" ${opt_suites[*]} " + for suite in "${opt_exclude[@]}"; do + suites_str="${suites_str/ "$suite" / }" + done + # shellcheck disable=SC2206 # see comment at top of block + opt_suites=( ${suites_str} ) + (( "${#opt_suites[@]}" )) || usage +fi + files_base_commit= # shellcheck disable=SC2119 # this is a silly warning case "$opt_files" in @@ -149,6 +181,21 @@ if_verbose() { fi } +# usage: maybe_time LABEL COMMAND... +# +# Run the given command. +# Then if $opt_verbose, print the command's elapsed time, +# including the given label. +maybe_time() { + label="$1"; shift + if [ -z "${opt_verbose}" ]; then + "$@" + else + local TIMEFORMAT=$'\n'$"${label} elapsed time: %1lR" + time "$@" + fi +} + # usage: grep_quiet_hungry GREP_ARGUMENTS... # # Just like `grep --quiet` aka `grep -q`, except this consumes the @@ -533,16 +580,17 @@ for suite in "${opt_suites[@]}"; do if_verbose echo "${divider_line}" echo "Running $suite..." case "$suite" in - analyze) run_analyze ;; - test) run_test ;; - flutter_version) run_flutter_version ;; - build_runner) run_build_runner ;; - l10n) run_l10n ;; - drift) run_drift ;; - pigeon) run_pigeon ;; - icons) run_icons ;; - android) run_android ;; - shellcheck) run_shellcheck ;; + analyze) maybe_time "$suite" run_analyze ;; + test) maybe_time "$suite" run_test ;; + flutter_version) + maybe_time "$suite" run_flutter_version ;; + build_runner) maybe_time "$suite" run_build_runner ;; + l10n) maybe_time "$suite" run_l10n ;; + drift) maybe_time "$suite" run_drift ;; + pigeon) maybe_time "$suite" run_pigeon ;; + icons) maybe_time "$suite" run_icons ;; + android) maybe_time "$suite" run_android ;; + shellcheck) maybe_time "$suite" run_shellcheck ;; *) echo >&2 "Internal error: unknown suite $suite" ;; esac || failed+=( "$suite" ) done