gitea: move workflows to .gitea, disable caches; settle the keystroke flake
Gitea prep: .github becomes .gitea (the act runner looks there), and every actions/cache + Swatinem/rust-cache step is commented out until the self-hosted instance has a cache provisioned. The remaining marketplace actions (checkout/upload-artifact are act-compatible; msys2/setup-msys2, dtolnay/rust-toolchain and softprops/action-gh-release need a runner test / replacement) are a follow-up. tests: the two gpui keystroke tests that flaked on Windows CI (undo pair, snapping toggle — each once, values identical to the pass state, Global-route keys) now dispatch each key with a double park. The root cause is not fully pinned: the loss happens inside gpui's synthetic key dispatch on Windows (both tests hold every test lock; production is unaffected). The CI retry-once remains the backstop. The earlier idea of advancing the simulated clock to flush gpui's pending-input timer is off the table: the mock engine's playback ticks with executor time, so a clock advance moves the playhead out from under the assertions (observed: playhead 14 vs expected 9).
This commit is contained in:
@@ -97,17 +97,17 @@ jobs:
|
||||
echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV"
|
||||
echo "OCIO_RS_LINK=static" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Cache cargo artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: oak-${{ matrix.distro }}
|
||||
cache-on-failure: true
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
|
||||
# uses: Swatinem/rust-cache@v2
|
||||
# with:
|
||||
# shared-key: oak-${{ matrix.distro }}
|
||||
# cache-on-failure: true
|
||||
|
||||
- name: Cache project FFmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cache/ffmpeg
|
||||
key: ffmpeg-${{ matrix.distro }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache project FFmpeg)
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: .cache/ffmpeg
|
||||
# key: ffmpeg-${{ matrix.distro }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
|
||||
- name: Build project FFmpeg (static, GPL + free codecs + hwaccel)
|
||||
run: tooling/ffmpeg/build-ffmpeg.sh
|
||||
@@ -172,17 +172,17 @@ jobs:
|
||||
echo "OCIO_RS_ENABLE_REAL=1" >> "$GITHUB_ENV"
|
||||
echo "OCIO_RS_LINK=static" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Cache cargo artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: oak-appimage
|
||||
cache-on-failure: true
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
|
||||
# uses: Swatinem/rust-cache@v2
|
||||
# with:
|
||||
# shared-key: oak-appimage
|
||||
# cache-on-failure: true
|
||||
|
||||
- name: Cache project FFmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cache/ffmpeg
|
||||
key: ffmpeg-appimage-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache project FFmpeg)
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: .cache/ffmpeg
|
||||
# key: ffmpeg-appimage-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
|
||||
- name: Build project FFmpeg (static, GPL + free codecs + hwaccel)
|
||||
run: tooling/ffmpeg/build-ffmpeg.sh
|
||||
@@ -239,17 +239,17 @@ jobs:
|
||||
echo "PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig/openjpeg"
|
||||
} >> "$GITHUB_ENV"
|
||||
|
||||
- name: Cache cargo artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: oak-workspace
|
||||
cache-on-failure: true
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
|
||||
# uses: Swatinem/rust-cache@v2
|
||||
# with:
|
||||
# shared-key: oak-workspace
|
||||
# cache-on-failure: true
|
||||
|
||||
- name: Cache project FFmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cache/ffmpeg
|
||||
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache project FFmpeg)
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: .cache/ffmpeg
|
||||
# key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
|
||||
- name: Build project FFmpeg (static, GPL + free codecs + hwaccel)
|
||||
run: |
|
||||
@@ -367,17 +367,17 @@ jobs:
|
||||
"$BS"
|
||||
grep -q 'OCIO_RS_NO_MSVC_INCLUDES' "$BS"
|
||||
|
||||
- name: Cache cargo artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: oak-workspace
|
||||
cache-on-failure: true
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
|
||||
# uses: Swatinem/rust-cache@v2
|
||||
# with:
|
||||
# shared-key: oak-workspace
|
||||
# cache-on-failure: true
|
||||
|
||||
- name: Cache project FFmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cache/ffmpeg
|
||||
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache project FFmpeg)
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: .cache/ffmpeg
|
||||
# key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
|
||||
- name: Build project FFmpeg (static, GPL + free codecs + hwaccel)
|
||||
run: |
|
||||
@@ -147,21 +147,21 @@ jobs:
|
||||
# ------------------------------------------------------------------
|
||||
# Covers the whole target/ dir plus ~/.cargo; shared across branches
|
||||
# of the same OS.
|
||||
- name: Cache cargo artifacts
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: oak-workspace
|
||||
cache-on-failure: true
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache cargo artifacts)
|
||||
# uses: Swatinem/rust-cache@v2
|
||||
# with:
|
||||
# shared-key: oak-workspace
|
||||
# cache-on-failure: true
|
||||
|
||||
# The project FFmpeg (release/8.0, static, all free codecs + hwaccel)
|
||||
# is built by tooling/ffmpeg/build-ffmpeg.sh — 10-20 min on a cold
|
||||
# cache. It does not depend on the Rust toolchain, so key it on the
|
||||
# script itself and keep it out of rust-cache.
|
||||
- name: Cache project FFmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .cache/ffmpeg
|
||||
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
# TEMP: cache disabled until the Gitea instance cache is provisioned (Cache project FFmpeg)
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: .cache/ffmpeg
|
||||
# key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Project FFmpeg (script + FFMPEG_DIR; see docs/build.md)
|
||||
+37
-48
@@ -2742,7 +2742,9 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::oakui::EngineGateway as _;
|
||||
use gpui::timeline::TimelineDataSource as _;
|
||||
use gpui::{px, size, ExternalPaths, FileDropEvent, TestAppContext, VisualTestContext};
|
||||
use gpui::{
|
||||
px, size, AnyWindowHandle, ExternalPaths, FileDropEvent, TestAppContext, VisualTestContext,
|
||||
};
|
||||
|
||||
/// The 视图/View menu carries a 语言/Language submenu whose items are
|
||||
/// labeled in their own language and whose checkmark follows the active
|
||||
@@ -3188,23 +3190,20 @@ mod tests {
|
||||
let key = |keystroke: &str| gpui::Keystroke::parse(keystroke).unwrap();
|
||||
|
||||
// --- shuttle: l plays, k stops, j steps back ----------------------
|
||||
cx.dispatch_keystroke(window.into(), key("l"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "l");
|
||||
assert!(
|
||||
cx.read(|app| root.read(app).program_clock.read(app).is_playing()),
|
||||
"l starts playback"
|
||||
);
|
||||
cx.dispatch_keystroke(window.into(), key("k"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "k");
|
||||
assert!(
|
||||
!cx.read(|app| root.read(app).program_clock.read(app).is_playing()),
|
||||
"k stops playback"
|
||||
);
|
||||
for _ in 0..10 {
|
||||
cx.dispatch_keystroke(window.into(), key("right"));
|
||||
settle_key(cx, window.into(), "right");
|
||||
}
|
||||
cx.dispatch_keystroke(window.into(), key("j"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "j");
|
||||
assert_eq!(
|
||||
cx.read(|app| root.read(app).program_clock.read(app).current_frame()),
|
||||
Frame(9),
|
||||
@@ -3214,16 +3213,14 @@ mod tests {
|
||||
// --- in/out points: i marks the in at 9, o the out at 15 ----------
|
||||
cx.dispatch_keystroke(window.into(), key("i"));
|
||||
for _ in 0..6 {
|
||||
cx.dispatch_keystroke(window.into(), key("right"));
|
||||
settle_key(cx, window.into(), "right");
|
||||
}
|
||||
cx.dispatch_keystroke(window.into(), key("o"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "o");
|
||||
let workarea = cx.read(|app| root.read(app).engine.read(app).workarea());
|
||||
assert_eq!(workarea, Some((Frame(9), Frame(15))), "i/o set the work area");
|
||||
|
||||
// --- marker: m adds one at the playhead ---------------------------
|
||||
cx.dispatch_keystroke(window.into(), key("m"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "m");
|
||||
let markers = cx.read(|app| root.read(app).engine.read(app).markers());
|
||||
assert!(
|
||||
markers.iter().any(|marker| marker.frame == Frame(15)),
|
||||
@@ -3231,8 +3228,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// --- snapping: s toggles the timeline's snap flag ------------------
|
||||
cx.dispatch_keystroke(window.into(), key("s"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "s");
|
||||
assert!(
|
||||
!cx.read(|app| root.read(app).timeline.read(app).state.snap_enabled),
|
||||
"s toggles snapping off"
|
||||
@@ -3240,12 +3236,10 @@ mod tests {
|
||||
|
||||
// --- zoom: = zooms in, - zooms out ---------------------------------
|
||||
let zoom_before = cx.read(|app| root.read(app).timeline.read(app).state.zoom);
|
||||
cx.dispatch_keystroke(window.into(), key("="));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "=");
|
||||
let zoom_in = cx.read(|app| root.read(app).timeline.read(app).state.zoom);
|
||||
assert!(zoom_in > zoom_before, "= zooms the timeline in");
|
||||
cx.dispatch_keystroke(window.into(), key("-"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "-");
|
||||
let zoom_out = cx.read(|app| root.read(app).timeline.read(app).state.zoom);
|
||||
assert!(zoom_out < zoom_in, "- zooms the timeline out");
|
||||
|
||||
@@ -3261,26 +3255,22 @@ mod tests {
|
||||
})
|
||||
};
|
||||
let height_before = height(cx);
|
||||
cx.dispatch_keystroke(window.into(), key("secondary-="));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "secondary-=");
|
||||
assert_eq!(height(cx), height_before + 8.0, "⌘= grows the tracks");
|
||||
|
||||
// --- focused-panel routing: ⌘A / ⌘⇧A hit the timeline panel --------
|
||||
cx.update(|app| root.update(app, |app, _cx| app.focused_panel = Some(TIMELINE)));
|
||||
cx.dispatch_keystroke(window.into(), key("secondary-a"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "secondary-a");
|
||||
let selected = cx.read(|app| root.read(app).timeline.read(app).selection().len());
|
||||
assert!(selected > 0, "⌘A selects every clip via the timeline panel");
|
||||
cx.dispatch_keystroke(window.into(), key("secondary-shift-a"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "secondary-shift-a");
|
||||
let selected = cx.read(|app| root.read(app).timeline.read(app).selection().len());
|
||||
assert_eq!(selected, 0, "⌘⇧A deselects via the timeline panel");
|
||||
|
||||
// q/w (ripple-to-in/out) reach the panel but are not wired yet —
|
||||
// they fall through to the shell's placeholder, state untouched.
|
||||
cx.dispatch_keystroke(window.into(), key("q"));
|
||||
cx.dispatch_keystroke(window.into(), key("w"));
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "w");
|
||||
let workarea = cx.read(|app| root.read(app).engine.read(app).workarea());
|
||||
assert_eq!(
|
||||
workarea,
|
||||
@@ -3301,9 +3291,8 @@ mod tests {
|
||||
// Move the playhead inside the first clip (the → shortcut steps one
|
||||
// frame), then split with ⌘K: the mock sequence grows by one clip.
|
||||
for _ in 0..10 {
|
||||
cx.dispatch_keystroke(window.into(), gpui::Keystroke::parse("right").unwrap());
|
||||
settle_key(cx, window.into(), "right");
|
||||
}
|
||||
cx.run_until_parked();
|
||||
let playhead = cx.read(|app| root.read(app).program_clock.read(app).current_frame());
|
||||
assert_eq!(playhead, Frame(10), "→ steps the playhead");
|
||||
|
||||
@@ -3314,11 +3303,7 @@ mod tests {
|
||||
.map(|t| t.clips().len())
|
||||
.sum()
|
||||
});
|
||||
cx.dispatch_keystroke(
|
||||
window.into(),
|
||||
gpui::Keystroke::parse("secondary-k").unwrap(),
|
||||
);
|
||||
cx.run_until_parked();
|
||||
settle_key(cx, window.into(), "secondary-k");
|
||||
let clips_after: usize = cx.read(|app| {
|
||||
let engine = root.read(app).engine.read(app);
|
||||
(0..engine.track_count())
|
||||
@@ -3331,20 +3316,11 @@ mod tests {
|
||||
"split at the playhead adds a clip ({clips_before} → {clips_after})"
|
||||
);
|
||||
|
||||
// ⌘Z / ⌘⇧Z reach the engine's undo/redo (the mock counts the calls).
|
||||
// One key per park, like every other assertion in this test — the
|
||||
// two-keys-in-one-park variant intermittently lost the first
|
||||
// binding hit on Windows CI (undo dispatched 0, redo 1).
|
||||
cx.dispatch_keystroke(
|
||||
window.into(),
|
||||
gpui::Keystroke::parse("secondary-z").unwrap(),
|
||||
);
|
||||
cx.run_until_parked();
|
||||
cx.dispatch_keystroke(
|
||||
window.into(),
|
||||
gpui::Keystroke::parse("secondary-shift-z").unwrap(),
|
||||
);
|
||||
cx.run_until_parked();
|
||||
// ⌘Z / ⌘⇧Z reach the engine's undo/redo (the mock counts the
|
||||
// calls). settle_key flushes the deferred binding dispatch that
|
||||
// intermittently landed after the assert on Windows CI.
|
||||
settle_key(cx, window.into(), "secondary-z");
|
||||
settle_key(cx, window.into(), "secondary-shift-z");
|
||||
let (undo, redo) = cx.read(|app| root.read(app).engine.read(app).undo_redo_calls());
|
||||
assert!(
|
||||
undo >= 1 && redo >= 1,
|
||||
@@ -3913,6 +3889,19 @@ mod tests {
|
||||
// Project manager (M13 D4)
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
/// Dispatch a synthetic keystroke and settle with a double park.
|
||||
/// gpui's window key handling may defer the binding dispatch (its
|
||||
/// pending/repeat machinery); parking twice drains the executor
|
||||
/// across two idle cycles so a deferred delivery lands before the
|
||||
/// assertion. Deliberately does NOT advance the simulated clock —
|
||||
/// the mock engine's playback ticks with executor time, so a clock
|
||||
/// advance would move the playhead out from under the assertions.
|
||||
fn settle_key(cx: &mut TestAppContext, window: AnyWindowHandle, key: &str) {
|
||||
cx.dispatch_keystroke(window.into(), gpui::Keystroke::parse(key).unwrap());
|
||||
cx.run_until_parked();
|
||||
cx.run_until_parked();
|
||||
}
|
||||
|
||||
/// A running app shell on the mock engine (en-US), plus its root. The
|
||||
/// caller holds the language lock (the tests flip the process-global
|
||||
/// language).
|
||||
|
||||
Reference in New Issue
Block a user