Commit 604f2da53e

604f2da53efc32270918b9d94ca9fb7a4372a1cf

parent: f8856437fb

Unsigned

cmc <hello@cleberg.net> · 2026-09-20 01:33 UTC

Move the live suite's fixtures off krz/gitbay-ios (!116)

The issue and merge-request fixtures move to ios-smoke/ui-smoke-edit, the
repo the edit flow already commits to. krz/gitbay-ios stops accumulating
smoke issues and closed merge requests and no longer needs a ui-smoke
branch.

smoke-account.sh seeds ui-smoke divergent from main in the fixture repo —
the MR flows open one merge request each way, so each side needs a commit
the other lacks — and reruns now reach that step on an existing repo. The
milestone the issue flow assigns is created by the suite.

Closes #9

Layout: unified · split

gitbayUITests/LiveSmokeUITests.swift +41 −23
@@ -11,9 +11,10 @@ import XCTest
1111/// -only-testing:gitbayUITests ...
1212///
1313/// They run as the `ios-smoke` account, a krz admin that owns the
14/// scratch and fixture repositories (smoke-account.sh provisions it), and
15/// assume branch `ui-smoke` exists on krz/gitbay-ios. A signed-out device
16/// is signed in at setUp from TEST_RUNNER_GITBAY_UITEST_TOKEN.
14/// scratch and fixture repositories (smoke-account.sh provisions it).
15/// Everything they write goes to those, never to krz/gitbay-ios. A
16/// signed-out device is signed in at setUp from
17/// TEST_RUNNER_GITBAY_UITEST_TOKEN.
1718final class LiveSmokeUITests: XCTestCase {
1819
1920 private var app: XCUIApplication!
@@ -32,7 +33,11 @@ final class LiveSmokeUITests: XCTestCase {
3233 static let smokeUser = "ios-smoke"
3334 static let smokeProfileDescription = "Live UI smoke account for gitbay-ios"
3435 static let smokePGPEmail = "ios-smoke+pgp@gitbay.org"
35 static let editRepo = "\(smokeUser)/ui-smoke-edit"
36
37 /// The repository the write flows work in: the fixture issue and
38 /// merge requests, and the file testBlameAndEditFlows edits.
39 /// smoke-account.sh seeds it, with `main` and `ui-smoke` divergent.
40 static let fixtureRepo = "\(smokeUser)/ui-smoke-edit"
3641
3742 override func setUpWithError() throws {
3843 try XCTSkipUnless(
@@ -56,6 +61,8 @@ final class LiveSmokeUITests: XCTestCase {
5661 deleteScratchRepo()
5762 }
5863 if name.contains("testCreationAndEditingFlows") {
64 try requireFixtureRepo()
65 ensureFixtureMilestone()
5966 ensureFixtureIssue()
6067 try requireFixtureBranch()
6168 }
@@ -69,6 +76,7 @@ final class LiveSmokeUITests: XCTestCase {
6976 ensureOrgFixtures()
7077 }
7178 if name.contains("testCloseInFavourFlow") {
79 try requireFixtureRepo()
7280 try requireFixtureBranch()
7381 closeSmokeMergeRequests()
7482 try openSupersedeFixtures()
@@ -143,7 +151,7 @@ final class LiveSmokeUITests: XCTestCase {
143151 "--title", Self.successorTitle])
144152 let open = openSmokeMergeRequests().map { $0.title }
145153 try XCTSkipUnless(open.contains(Self.supersededTitle) && open.contains(Self.successorTitle), """
146 could not open both fixture merge requests on krz/gitbay-ios \
154 could not open both fixture merge requests on \(Self.fixtureRepo) \
147155 (have \(open)); the ui-smoke branch may be level with main.
148156 """)
149157 }
@@ -175,6 +183,19 @@ final class LiveSmokeUITests: XCTestCase {
175183 _ = runCommand(["repo", "delete", Self.scratchRepo + "-2", "--yes"])
176184 }
177185
186 /// The milestone the editing flow assigns. Created rather than
187 /// required: unlike a branch, the API can make one.
188 static let fixtureMilestone = "v1.0.0"
189
190 private func ensureFixtureMilestone() {
191 guard let data = readCommand(["milestone", "list", Self.fixtureRepo, "--state", "all"]),
192 let envelope = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
193 else { return }
194 let rows = envelope["data"] as? [[String: Any]] ?? []
195 if rows.contains(where: { $0["title"] as? String == Self.fixtureMilestone }) { return }
196 _ = runCommand(["milestone", "create", Self.fixtureRepo, Self.fixtureMilestone])
197 }
198
178199 /// The issue the editing flow works on. It is a fixture, not a real
179200 /// issue: pinning the test to whatever issue happened to be open put
180201 /// it at the mercy of the project moving on, and it duly broke when
@@ -200,8 +221,6 @@ final class LiveSmokeUITests: XCTestCase {
200221 )
201222 }
202223
203 static let fixtureRepo = "krz/gitbay-ios"
204
205224 /// The MR flow needs a source branch carrying a commit main does not
206225 /// have. Nothing in the app or the API can create a branch — that is
207226 /// a push — so this only checks, and says so plainly rather than
@@ -214,9 +233,9 @@ final class LiveSmokeUITests: XCTestCase {
214233 else { return } // no token, or the instance is unreachable
215234 let names = branches.compactMap { $0["name"] as? String }
216235 try XCTSkipUnless(names.contains("ui-smoke"), """
217 krz/gitbay-ios has no ui-smoke branch. The MR flow opens a \
218 merge request from it; recreate it with a commit main does \
219 not have (see .gitbay/ui-smoke.md on that branch).
236 \(Self.fixtureRepo) has no ui-smoke branch. The MR flows open \
237 one merge request each way between it and main, so each side \
238 needs a commit the other lacks; smoke-account.sh seeds both.
220239 """)
221240 }
222241
@@ -265,9 +284,9 @@ final class LiveSmokeUITests: XCTestCase {
265284 /// MR create, MR close. One test so the flows share navigation and
266285 /// the writes happen exactly once.
267286 func testCreationAndEditingFlows() throws {
268 openRepo("krz/gitbay-ios")
287 openRepo(Self.fixtureRepo)
269288
270 // --- the fixture issue: milestone picker assigns v1.0.0 ---
289 // --- the fixture issue: milestone picker assigns the fixture ---
271290 app.staticTexts["Issues"].firstMatch.tap()
272291 let issueRow = app.staticTexts
273292 .containing(NSPredicate(format: "label CONTAINS 'ui-smoke fixture'")).firstMatch
@@ -280,11 +299,11 @@ final class LiveSmokeUITests: XCTestCase {
280299 XCTAssertTrue(milestoneMenu.waitForExistence(timeout: 10))
281300 milestoneMenu.tap()
282301 let milestoneChoice = app.buttons
283 .containing(NSPredicate(format: "label BEGINSWITH 'v1.0.0'")).firstMatch
302 .containing(NSPredicate(format: "label BEGINSWITH %@", Self.fixtureMilestone)).firstMatch
284303 XCTAssertTrue(milestoneChoice.waitForExistence(timeout: 5), "milestone menu did not open")
285304 milestoneChoice.tap()
286305 // The reload renders the assigned milestone in the header row.
287 XCTAssertTrue(app.staticTexts["v1.0.0"].firstMatch
306 XCTAssertTrue(app.staticTexts[Self.fixtureMilestone].firstMatch
288307 .waitForExistence(timeout: 10), "milestone not shown after assign")
289308
290309 // --- the fixture issue: edit sheet saves (content unchanged) ---
@@ -415,18 +434,17 @@ final class LiveSmokeUITests: XCTestCase {
415434 keys.tap()
416435 }
417436
418 /// The edit flow saves a change to a real file. Seeding a
419 /// repository's first commit is a push, which no test can make, so
420 /// this only checks — and says why, rather than failing later at
421 /// "ios-smoke/ui-smoke-edit not in the repo list".
437 /// Seeding a repository's first commit is a push, which no test can
438 /// make, so this only checks — and says why, rather than failing
439 /// later at "ios-smoke/ui-smoke-edit not in the repo list".
422440 private func requireFixtureRepo() throws {
423 guard let data = readCommand(["repo", "show", Self.editRepo]),
441 guard let data = readCommand(["repo", "show", Self.fixtureRepo]),
424442 let envelope = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
425443 else { return } // no token, or the instance is unreachable
426444 try XCTSkipUnless(envelope["data"] != nil, """
427 \(Self.editRepo) is missing. The edit flow saves a change to \
428 notes.txt in it; gitbayUITests/smoke-account.sh seeds it (or \
429 push it by hand, see that script) and run again.
445 \(Self.fixtureRepo) is missing. The write flows work in it; \
446 gitbayUITests/smoke-account.sh seeds it (or push it by hand, \
447 see that script) and run again.
430448 """)
431449 }
432450
@@ -1186,7 +1204,7 @@ extension LiveSmokeUITests {
11861204 // previous query, and clearing it from the harness is unreliable.
11871205 app.terminate()
11881206 app.launch()
1189 openRepo(Self.editRepo)
1207 openRepo(Self.fixtureRepo)
11901208 app.staticTexts["Files"].firstMatch.tap()
11911209 let notes = app.staticTexts["notes.txt"].firstMatch
11921210 XCTAssertTrue(notes.waitForExistence(timeout: 15), "notes.txt not in the tree")
gitbayUITests/smoke-account.sh +53 −16
@@ -4,7 +4,9 @@
44# what already exists, so a failed run is rerun as is. It creates the
55# account with a fresh SSH key (~/.ssh/gitbay-ios-smoke), makes it a krz
66# admin, sets its profile description, registers a PGP key, and pushes
7# the ios-smoke/ui-smoke-edit fixture that testBlameAndEditFlows edits.
7# the ios-smoke/ui-smoke-edit fixture the write flows work in: notes.txt
8# for testBlameAndEditFlows, and a ui-smoke branch divergent from main
9# for the merge-request flows.
810# LiveSmokeUITests asserts on the same values, so keep the two in step.
911set -eu
1012
@@ -39,37 +41,72 @@ if ! as_smoke pgp list --json | grep -q "$pgp_email"; then
3941 rm -rf "$gnupg"
4042fi
4143
42if as_smoke repo show "$user/ui-smoke-edit" --json > /dev/null 2>&1; then
43 echo "$user/ui-smoke-edit exists"
44 exit 0
45fi
46as_smoke repo create "$user/ui-smoke-edit"
44repo=$user/ui-smoke-edit
45url=ssh://git@gitbay.org/$repo.git
4746work=$(mktemp -d)
48git -C "$work" init -q -b main
49cat > "$work/README.md" <<'EOF'
47trap 'rm -rf "$work"' EXIT
48
49commit_in_work() {
50 git -C "$work" add -A
51 git -C "$work" -c user.name="$user" -c user.email="$user@gitbay.org" \
52 -c commit.gpgsign=false commit -q -m "$1"
53}
54
55push_work() {
56 GIT_SSH_COMMAND="$smoke_ssh" git -C "$work" push -q "$url" "$1"
57}
58
59if as_smoke repo show "$repo" --json > /dev/null 2>&1; then
60 echo "$repo exists"
61 GIT_SSH_COMMAND="$smoke_ssh" git clone -q "$url" "$work"
62else
63 as_smoke repo create "$repo"
64 git -C "$work" init -q -b main
65 cat > "$work/README.md" <<'EOF'
5066# ui-smoke-edit
5167
5268A fixture repository for the gitbay-ios live UI smoke suite. `notes.txt`
53is edited by `testBlameAndEditFlows` on every run.
69is edited by `testBlameAndEditFlows` on every run, and the `ui-smoke`
70branch is what the merge-request flows open merge requests from.
5471
5572Nothing in the app or the JSON API can seed a repository's first commit
5673(that is a push), so the suite only checks that this repo exists and
5774skips when it does not. `gitbayUITests/smoke-account.sh` in krz/gitbay-ios
5875is what created it.
5976EOF
60cat > "$work/notes.txt" <<'EOF'
77 cat > "$work/notes.txt" <<'EOF'
6178Scratch content for the live UI smoke suite.
6279
6380testBlameAndEditFlows opens this file and saves an edit through the app,
6481which is how the file-editing path is verified end to end. The text does
6582not matter; the file existing does.
6683EOF
67git -C "$work" add -A
68git -C "$work" -c user.name="$user" -c user.email="$user@gitbay.org" -c commit.gpgsign=false \
69 commit -q -m 'fixture repo for the live smoke suite'
70GIT_SSH_COMMAND="$smoke_ssh" \
71 git -C "$work" push -q "ssh://git@gitbay.org/$user/ui-smoke-edit.git" main
72rm -rf "$work"
84 commit_in_work 'fixture repo for the live smoke suite'
85 push_work main
86fi
87
88# The MR flows open one merge request each way between ui-smoke and
89# main, so each side needs a commit the other lacks. Only a push can
90# make a branch, which is why this lives here and not in the suite.
91if ! as_smoke repo refs "$repo" --json | grep -q '"ui-smoke"'; then
92 git -C "$work" checkout -q -b ui-smoke
93 cat > "$work/ui-smoke.md" <<'EOF'
94This branch exists so the live UI smoke suite has a merge request to
95open. It is never merged: the suite opens merge requests both ways
96between it and main, and closes them again.
97EOF
98 commit_in_work 'ui-smoke: a commit main does not have'
99 push_work ui-smoke
100
101 git -C "$work" checkout -q main
102 cat > "$work/main.md" <<'EOF'
103The counterpart of ui-smoke.md: a commit on main that the ui-smoke
104branch does not have, so a merge request from main to ui-smoke has
105something to carry.
106EOF
107 commit_in_work 'main: a commit ui-smoke does not have'
108 push_work main
109fi
73110
74111echo "Mint the suite's token with:"
75112echo " $smoke_ssh git@gitbay.org token create --name ui-smoke --scope full --ttl 30d"