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
525 changes: 512 additions & 13 deletions .github/skills/ghpmv-e2e-validation/SKILL.md

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions docs/BROWSER_AUTOMATION_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ GraphQL と Playwright を組み合わせた View・Workflow 移行の詳細設
| Board の列フィールド | GraphQL `verticalGroupByFields` | **UI**("Column by") | |
| sort(複数キー+方向) | GraphQL `sortByFields`(`ProjectV2SortByField.direction`) | **UI** | |
| **Slice by** | ❌ API に無い → **UI で読む** | **UI** | |
| **Field sum** | ❌ API に無い → **UI で読む** | **UI** | |
| **Field sum** | ❌ API に無い → **UI で読む** | **UI** | Board と grouped Table / Roadmap。Count、複数 Number field、空集合を complete-set 同期 |
| **Roadmap 設定(Dates / Zoom / Markers)** | ❌ API に無い → **UI で読む** | **UI** | |
| タブの並び順 | **UI**(`navigation "Select view"` 内のsaved tab `href`順) | **UI**(タブの drag & drop) | GraphQL `POSITION`は現行UIのsaved-tab順と乖離する場合がある。`ViewSnapshot.tabPosition`はschema v1のnullable additive field |

Expand Down Expand Up @@ -153,7 +153,7 @@ internal static class Sel
| V-1 | Table 基本 | 表示フィールド選択と列順 |
| V-2 | Table + group-by | 任意フィールド 1 つ(Status/Single-select/Iteration など) |
| V-3 | Table + sort | export は複数キーを保持。v1 browser import が適用するのは先頭キーのみ |
| V-4 | Table + Field sum | グループ見出しに合計表示する Number フィールド群 |
| V-4 | Table / Board / Roadmap + Field sum | grouped Table / Roadmap と Board で Count、複数 Number field、空集合を complete-set 同期 |
| V-5 | Board | Column by(Status / 任意 single-select / iteration) |
| V-6 | Board + swimlane | Group by(横帯)との組み合わせ |
| V-7 | Roadmap | Dates(date フィールド対 or iteration)、Zoom(Month/Quarter/Year)、Markers |
Expand All @@ -171,7 +171,7 @@ internal static class Sel
2. `Sel.ViewMenuButton(page).ClickAsync()` → 開いた menu の accessible name / checked state を取得
3. メニュー項目のラベルから現在値を読む:
- "Slice by: <field>" → `ViewUiSnapshot.SliceBy`
- "Field sum: <fields>" → `ViewUiSnapshot.FieldSum`
- "Field sum: <fields>" の子 menu を開き、checked `menuitemcheckbox` 全件 → `ViewUiSnapshot.FieldSum` (summary は 3 件以上で `1 more` に省略されるため使用しない)
- Roadmap のみ: "Dates: <...>", "Zoom level: <Month|Quarter|Year>", "Markers: <...>"
4. Esc でメニューを閉じる
5. `navigation "Select view"`内のsaved tab `href`をDOM順に列挙し、View numberへ変換して`tabPosition`を付与する
Expand All @@ -190,7 +190,7 @@ EnrichView(spec, targetViewNumber):
3. Group by / Swimlanes: layout に応じた項目で spec.GroupBy を選択
4. Sort by: View menu → "Sort by" → 先頭キーを選択 → 必要なら方向トグル
5. Slice by: ViewOptions → "Slice by" → spec.SliceBy
6. Field sum: ViewOptions → "Field sum" → spec.FieldSum の各フィールドをチェック
6. Field sum: Board または grouped Table / Roadmap で ViewOptions → "Field sum" → 子 menu 内だけを対象に spec.FieldSum の complete set へ同期(Count と空集合を含む)
7. Roadmap のみ: "Dates" → 開始/終了フィールド対 or iteration を選択、"Zoom level"、"Markers" のチェック群
8. 保存: View menu → "Save view" → alertdialog の "Save"(dialog が出ない UI variant では直接保存)
9. 全 View 設定の適用後、target のDOM `href`順と snapshot順から最小移動計画を作り、必要なタブだけdrag-and-drop
Expand Down Expand Up @@ -314,12 +314,12 @@ browser importer 自体は各 view / workflow の適用直後に完全な read-b

`GHPMV_TEST_ORG` に作る基準プロジェクト(セットアップスクリプトは可能な限り GraphQL、View/Workflow 部分は初回手動 + 本ツール自身でのブートストラップ):

- フィールド: Status(custom option 4 つ、色・説明付き)/ Priority(single-select)/ Estimate(number)/ Start・End(date)/ Sprint(iteration, 2 週間, 完了済み 1 + 未来 2)/ Notes(text)
- Views(§3.1 の V-1〜V-9 を全て網羅する 4 view):
1. "Backlog" — Table, filter, hidden fields, 2 キー sort, Field sum(Estimate), group-by Status
2. "Board" — Board, Column by Priority, swimlane = Sprint, Slice by Assignees
3. "Roadmap" — Roadmap, Dates = Start/End, Zoom = Quarter, Markers 有効
4. "Everything" — Table, 設定ほぼデフォルト(デフォルト値の透過を確認)
- フィールド: Status(Todo / In Progress / Done)/ Fixture Text(text)/ Fixture Number・Fixture Number 2(number)/ Fixture Date(date)/ Fixture Select(single-select)/ Fixture Sprint(iteration, 2 週間)/ Fixture Areas(project multi-select)/ Fixture Teams(organization multi-select Issue Field)
- Views(§3.1 の V-1〜V-10 を網羅):
1. "View 1" — grouped Table, filter, sort, Slice by, Field sum=[Count, Fixture Number, Fixture Number 2]
2. "Fixture Board" — Board, Column by, swimlane, Field sum=[Fixture Number]
3. "Fixture Roadmap" — grouped Roadmap, Field sum=[Fixture Number 2], Dates, Zoom, Markers
4. "Fixture Empty Sums" — grouped Table, Field sum=[]
- Workflows: W-1〜W-8 を非デフォルト Status 値で有効化、W-9 を 2 本(別リポ + 別フィルター)。1 つは disabled のまま設定を持たせる(§4.3 の D0 論点の検証用)
- Items: issue 10 / PR 3 / draft 3(archived 2 を含む)

Expand Down
84 changes: 62 additions & 22 deletions docs/MANUAL_TEST_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ EMU / SAML / OIDC backed organization の場合は、PAT と browser session の

Team link の手動 E2E では共有 Team を変更せず、source/target の各 organization にこのテスト専用 Team を作成してください。source fixture には `--fixture-team <source-team-slug>` を渡します。target Team は同じ slug、または renamed mapping を確認する別 slug にします。

Views の作成と name / layout / filter / visible fields は GraphQL API で設定します。標準 fixture には API 未対応の View 設定、非自明な `Fixture Roadmap → View 1 → Fixture Board` の tab order、Workflows も含まれるため、`ghpmv setup --fixture-ui` は API View import の後に C# の Playwright layer で補完します。手動で UI をぽちぽち濃くする必要はありません。
Views の作成と name / layout / filter / visible fields は GraphQL API で設定します。標準 fixture には API 未対応の View 設定、非自明な `Fixture Roadmap → View 1 → Fixture Board → Fixture Empty Sums` の tab order、Workflows も含まれるため、`ghpmv setup --fixture-ui` は API View import の後に C# の Playwright layer で補完します。手動で UI をぽちぽち濃くする必要はありません。

---

Expand Down Expand Up @@ -339,10 +339,11 @@ dotnet run --project src/Ghpmv.Cli -- setup `
このコマンドは、既存 Project に対して標準テスト用の以下を作成します。

- Views
- `View 1`: Table、filter、sort、Slice by、visible fields
- `View 1`: grouped Table、filter、sort、Slice by、Field sum=`Count` + `Fixture Number` + `Fixture Number 2`、visible fields
- `Fixture Board`: Board、Column by、Swimlanes、Field sum
- `Fixture Roadmap`: Roadmap、date fields、Quarter zoom、markers
- tab order: `Fixture Roadmap` → `View 1` → `Fixture Board`
- `Fixture Roadmap`: grouped Roadmap、Field sum=`Fixture Number 2`、date fields、Quarter zoom、markers
- `Fixture Empty Sums`: grouped Table、Field sum の空選択
- tab order: `Fixture Roadmap` → `View 1` → `Fixture Board` → `Fixture Empty Sums`
- Workflows
- item state 系 built-in workflows
- `Auto-add to project`
Expand All @@ -353,26 +354,33 @@ dotnet run --project src/Ghpmv.Cli -- setup `

- `dotnet run --project src/Ghpmv.Cli -- setup --browsers` が完了している。
- `dotnet run --project src/Ghpmv.Cli -- login --profile source` で source org を編集できる browser session が保存されている。
- 対象 Project は `ghpmv setup --fixture` で作成済みで、`Fixture Text` / `Fixture Number` / `Fixture Date` / `Fixture Select` / `Fixture Sprint` / `Fixture Teams` fields と `$env:GHPMV_FIXTURE_REPO` repository が存在する。
- 対象 Project は `ghpmv setup --fixture` で作成済みで、`Fixture Text` / `Fixture Number` / `Fixture Number 2` / `Fixture Date` / `Fixture Select` / `Fixture Sprint` / `Fixture Teams` fields と `$env:GHPMV_FIXTURE_REPO` repository が存在する。

`ghpmv setup --fixture-ui` が GitHub UI 変更などで失敗した場合のみ、フォールバックとして Source Project を開き、以下を手動で設定します。

Views:

- タブを `Fixture Roadmap` → Table view → Board view の非自明な順に並べる
- Table view
- filter を設定
- hidden / visible fields を調整
- 2 key sort
- タブを `Fixture Roadmap` → `View 1``Fixture Board` → `Fixture Empty Sums` の順に並べる
- `View 1` (Table)
- filter=`status:Todo`
- visible fields を標準 fixture に合わせる
- Sort by=`Fixture Number` ascending
- group by Status
- Field sum に Number field を設定
- Board view
- Column by Status または Single-select field
- Swimlanes / Slice by を設定
- Roadmap view
- Date field または Iteration を設定
- Zoom を Quarter に設定
- markers を有効化
- Slice by=`Fixture Select`
- Field sum=`Count`, `Fixture Number`, `Fixture Number 2`
- `Fixture Board` (Board)
- Column by=`Fixture Select`
- Swimlanes=`Status`
- Field sum=`Fixture Number`
- `Fixture Roadmap` (Roadmap)
- group by Status
- Field sum=`Fixture Number 2`
- Dates=`Fixture Date` → `Fixture Sprint end`
- Zoom=`Quarter`
- Markers=`Fixture Date`
- `Fixture Empty Sums` (Table) を作成
- group by Status
- Field sum は空(`Count` を含めてすべて解除)

Workflows:

Expand Down Expand Up @@ -488,6 +496,20 @@ dotnet run --project src/Ghpmv.Cli -- export `
- linked Team がある場合は `team-mappings.csv` が生成され、source 値は `organization/slug` になっている。
- source UI の Views / Workflows / collaborators に関する warning がない、または想定内である。
- 各 View の `tabPosition` が 0 から始まる source UI 順で保存され、view `number` 順とは独立している。
- `snapshot.json` の View UI 設定が 5.2 の標準 fixture と一致する。
- `View 1`: `fieldSum=["Count","Fixture Number","Fixture Number 2"]`
- `Fixture Board`: `fieldSum=["Fixture Number"]`
- `Fixture Roadmap`: `fieldSum=["Fixture Number 2"]`
- `Fixture Empty Sums`: `fieldSum=[]`(submenu を取得できた空選択。control/submenu を取得できない場合は View UI 未取得 warning)

3 件以上の Field sum は GitHub UI で `1 more` と省略されますが、snapshot には実フィールド名が全件必要です。既存の snapshot 確認に次を追加し、別 export は実行しません。

```powershell
$snapshot = Get-Content "$env:GHPMV_SNAPSHOT_DIR/snapshot.json" -Raw | ConvertFrom-Json
$snapshot.views |
Where-Object name -in @('View 1', 'Fixture Board', 'Fixture Roadmap', 'Fixture Empty Sums') |
Select-Object name, groupByFields, @{ Name = 'fieldSum'; Expression = { @($_.ui.fieldSum) -join ', ' } }
```

### 7.2 Mapping CSV を補完

Expand Down Expand Up @@ -560,7 +582,7 @@ dotnet run --project src/Ghpmv.Cli -- import `

出力された target Project URL と project number を控えます。

stdout の既存行に加えて `status-updates: created=... resumed=... already-complete=...` が出ることを確認します。同じ snapshot directory と `--project-number <target-project-number> --on-conflict update` で再実行し、`created=0`、`already-complete=5` となり、UI の履歴件数が増えないことも確認します。本文が同じ Status Update が複数あっても内容で統合されず、snapshot の各 sequence が1件ずつ残ることが合格条件です
stdout の既存行に加えて `status-updates: created=... resumed=... already-complete=...` が出ることを確認します。再実行確認は 7.4 の Field sum drift 後に一度だけ行い、同じ snapshot directory と `--project-number <target-project-number>` で drift の修復と idempotence を同時に検証します。`created=0`、`already-complete=5` となり、UI の履歴件数、Field、View が増えないことが合格条件です。`--project-number` は既存 Project を常に更新するため `--on-conflict` とは併用しません

template 化は import の最終書き込み段です。stderr で Items / Status Updates / API View / browser View enrichment・tab order / Workflows の完了後に `Marking the target project as a template as the final import stage...` が出ることを確認します。Organization の **Projects → Templates** と Create project ダイアログで target Project がテンプレートとして表示されることも確認します。

Expand Down Expand Up @@ -601,6 +623,15 @@ OK: the target project matches the snapshot.

human-readable category table と `verify-report.json` の両方に `StatusUpdate: Match` が additive に含まれ、`Project: Match` に template 属性の一致が反映されることを確認します。Status Updates は note 追加後の本文、status、startDate、targetDate、snapshot sequence を比較し、target API が新しく付けた creator/createdAt 自体は比較対象外です。

Field sum はこの既存 round trip の中で確認し、別の export/import シナリオは実行しません。

1. 初回 verify で `View: Match` を確認し、`View 1` / `Fixture Roadmap` の Field sum menu と group header、および `Fixture Empty Sums` に sum がないことを 8.4 と同時に目視します。
2. target の `View 1` で `Fixture Number 2` だけを解除して保存し、同じ verify command を再実行します。非ゼロ終了と `view 'View 1': field sum mismatch` を確認します。
3. 7.3 の再 import を `--project-number <target-project-number>` で一度だけ実行し、Status Updates の idempotence と Field sum の復元を同時に確認します。
4. 7.4 の verify をもう一度実行し、`View: Match`、`Fixture Number 2` の復元、4 fixture Views が各 1 件だけ存在することを確認します。

この統合により追加実行は drift verify、修復用の再 import、最終 verify の 3 command だけです。証跡は 11、削除は 10 の既存手順へまとめます。

warning / error が出た場合は、次の観点で切り分けます。

| 症状 | よくある原因 | 対応 |
Expand Down Expand Up @@ -649,10 +680,12 @@ warning / error が出た場合は、次の観点で切り分けます。
### 8.4 Views

- [ ] Table view の filter / visible fields / sort / group by / field sum が一致。
- [ ] Board view の Column by / Swimlanes / Slice by が一致。
- [ ] Roadmap view の date fields / zoom / markers が一致。
- [ ] Board view の Column by / Swimlanes / Slice by / field sum が一致。
- [ ] Roadmap view の group by / field sum / date fields / zoom / markers が一致。
- [ ] grouped Table / Roadmap の group header に `Count` と選択した Number field の合計が source と同じ組み合わせで表示される。
- [ ] `Fixture Empty Sums` の group header に Field sum が表示されない。
- [ ] View 名が一致。
- [ ] View tab order が `Fixture Roadmap` → `View 1` → `Fixture Board` で一致。
- [ ] View tab order が `Fixture Roadmap` → `View 1` → `Fixture Board` → `Fixture Empty Sums` で一致。
- [ ] 通常幅とタブが画面幅を超える狭い幅の両方で source/target 順が一致。
- [ ] import を再実行しても既に正しい tab order は変化しない。

Expand Down Expand Up @@ -750,6 +783,13 @@ Export result:
Import result:
Verify result:

Field sum source views:
Field sum snapshot values:
Field sum initial verify:
Field sum drift verify:
Field sum rerun verify:
Field sum screenshots/observations:

Warnings:
-

Expand Down
4 changes: 2 additions & 2 deletions docs/MIGRATION_SCOPE.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ View names, layouts, filters, and ordered visible fields are imported through th

| Area | Supported? | Notes |
|---|---:|---|
| Table views | ✅ / best effort | Name, layout, filter, and visible-field order use GraphQL. Group by, the first sort key, Slice by, and related display options use browser enrichment. Additional sort keys are exported but only the first is applied. |
| Table views | ✅ / best effort | Name, layout, filter, and visible-field order use GraphQL. Group by, the first sort key, Slice by, and grouped-view Field sum use browser enrichment. Field sums preserve Count, multiple Number fields, and an empty selection. Additional sort keys are exported but only the first is applied. |
| Board views | ✅ | Column by, Swimlanes and Field sum are tested. |
| Roadmap views | ✅ | Date fields, zoom level and markers are tested. |
| Roadmap views | ✅ | Date fields, zoom level, markers, and grouped-view Field sum are tested. Field sums preserve Count, multiple Number fields, and an empty selection. |
| View API settings | ✅ | Name, layout, filter, and ordered visible fields are migrated without browser automation. |
| View UI-only settings | ✅ | Grouping, sorting, slicing, field sums, and Roadmap settings are exported/imported by browser automation where the UI exposes them. |
| View tab order | ✅ with browser automation | The public GraphQL `POSITION` order can differ from the saved-tab order shown by GitHub. Browser-assisted export/verify read tab `href` values in DOM order, and browser-assisted import applies the minimum drag-and-drop moves after all View settings. API-only export leaves tab order uncaptured, API-only import warns when a snapshot contains it, and API-only verify marks it not verified. |
Expand Down
Loading