From 73da46c143b37cb2b26e9e624b8c39963ad52d77 Mon Sep 17 00:00:00 2001 From: whzy <2402686765@qq.com> Date: Fri, 26 Jun 2026 16:28:57 +0800 Subject: [PATCH] test(feishu): add local setup and smoke scripts --- .gitignore | 6 + .local/feishu-gitlink.env.example.ps1 | 30 ++ README.md | 10 + README.zh-CN.md | 10 + docs/FEISHU_ENVIRONMENT.md | 21 ++ docs/PR_VISUAL_GUIDE.md | 6 + docs/feishu-integration.md | 18 ++ reports/FEISHU_LOCAL_TESTING_GUIDE.md | 123 +++++-- reports/FEISHU_SMOKE_20260626.md | 140 +++----- scripts/feishu-gitlink-env-check.ps1 | 88 +++++ scripts/feishu-gitlink-screenshot-check.ps1 | 35 ++ scripts/feishu-gitlink-setup.ps1 | 199 ++++++++++++ scripts/feishu-gitlink-smoke.ps1 | 336 ++++++++++++++++++++ 13 files changed, 906 insertions(+), 116 deletions(-) create mode 100644 .local/feishu-gitlink.env.example.ps1 create mode 100644 scripts/feishu-gitlink-env-check.ps1 create mode 100644 scripts/feishu-gitlink-screenshot-check.ps1 create mode 100644 scripts/feishu-gitlink-setup.ps1 create mode 100644 scripts/feishu-gitlink-smoke.ps1 diff --git a/.gitignore b/.gitignore index bd0ccf8..5bdeb90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ gitlink-cli.exe /gitlink-cli +.local/* +!.local/ +!.local/feishu-gitlink.env.example.ps1 +*.local.ps1 +*.secret.* +reports/feishu-real-smoke-terminal.log diff --git a/.local/feishu-gitlink.env.example.ps1 b/.local/feishu-gitlink.env.example.ps1 new file mode 100644 index 0000000..61d98a5 --- /dev/null +++ b/.local/feishu-gitlink.env.example.ps1 @@ -0,0 +1,30 @@ +# Stable Feishu webhook +$env:FEISHU_WEBHOOK_URL="" +$env:FEISHU_WEBHOOK_SECRET="" + +# Feishu Open Platform +$env:FEISHU_APP_ID="" +$env:FEISHU_APP_SECRET="" + +# Feishu DocX / Wiki +$env:FEISHU_WIKI_URL="" +$env:FEISHU_WIKI_NODE_TOKEN="" +$env:FEISHU_FOLDER_TOKEN="" + +# Feishu Base / Bitable +$env:FEISHU_BASE_APP_TOKEN="" +$env:FEISHU_REPORT_TABLE_ID="" +$env:FEISHU_ISSUE_TABLE_ID="" +$env:FEISHU_PR_TABLE_ID="" +$env:FEISHU_CONTRIBUTOR_TABLE_ID="" +$env:FEISHU_TASK_TABLE_ID="" + +# Feishu Task +$env:FEISHU_TASK_PROJECT_ID="" +$env:FEISHU_TASK_SECTION_ID="" + +# GitLink real test input +$env:GITLINK_OWNER="" +$env:GITLINK_REPO="" +$env:GITLINK_TEST_PR_IDS="" +$env:GITLINK_TOKEN="" diff --git a/README.md b/README.md index e967337..c7e7f29 100644 --- a/README.md +++ b/README.md @@ -686,6 +686,16 @@ Details: - [Feishu environment variables](./docs/FEISHU_ENVIRONMENT.md) - [Feishu permission matrix](./reports/FEISHU_PERMISSION_MATRIX.md) +Local setup and smoke testing: + +```powershell +.\scripts\feishu-gitlink-setup.ps1 +.\scripts\feishu-gitlink-env-check.ps1 -Layer stable +.\scripts\feishu-gitlink-smoke.ps1 -Mode preview +``` + +The setup script stores real values only in `.local/feishu-gitlink.env.ps1`, which is ignored. + ### Dataset `dataset` manages and queries GitLink research datasets (title, description, diff --git a/README.zh-CN.md b/README.zh-CN.md index 46f95f2..6571f96 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -586,6 +586,16 @@ gitlink-cli feishu +task-create --from-workflow-json report.json --send --format - [飞书能力分层](./docs/FEISHU_CAPABILITY_LAYERS.md) - [飞书环境变量](./docs/FEISHU_ENVIRONMENT.md) - [飞书权限矩阵](./reports/FEISHU_PERMISSION_MATRIX.md) + +本地配置和 smoke 测试: + +```powershell +.\scripts\feishu-gitlink-setup.ps1 +.\scripts\feishu-gitlink-env-check.ps1 -Layer stable +.\scripts\feishu-gitlink-smoke.ps1 -Mode preview +``` + +真实值只会写入被忽略的 `.local/feishu-gitlink.env.ps1`,不要提交。 ### Raw API Shortcuts 未覆盖的接口可通过 Raw API 直接调用: diff --git a/docs/FEISHU_ENVIRONMENT.md b/docs/FEISHU_ENVIRONMENT.md index 71ecabc..eeff1c5 100644 --- a/docs/FEISHU_ENVIRONMENT.md +++ b/docs/FEISHU_ENVIRONMENT.md @@ -4,6 +4,26 @@ Date: 2026-06-26 Do not commit real values. Use a local shell profile, CI secret store, or test terminal session. +Recommended local workflow: + +```powershell +.\scripts\feishu-gitlink-setup.ps1 +.\scripts\feishu-gitlink-env-check.ps1 -Layer stable +.\scripts\feishu-gitlink-smoke.ps1 -Mode preview +``` + +`feishu-gitlink-setup.ps1` opens the relevant Feishu / GitLink pages, lets the user paste values locally, and writes only to: + +```text +.local/feishu-gitlink.env.ps1 +``` + +The real local env file is ignored. The tracked example is: + +```text +.local/feishu-gitlink.env.example.ps1 +``` + ## Stable Custom Bot Variables | Name | Purpose | Required | Used by | Sensitive | How to obtain | @@ -112,6 +132,7 @@ $env:GITLINK_TOKEN="REDACTED" ```text Never paste real secrets into committed docs. +Never paste real secrets into ChatGPT. Never print raw webhook URLs or app secrets in smoke reports. Do not commit tenant_access_token or user_access_token. Do not enable --send in shared scripts unless the target test enterprise is intentional. diff --git a/docs/PR_VISUAL_GUIDE.md b/docs/PR_VISUAL_GUIDE.md index 3d09734..1a210f2 100644 --- a/docs/PR_VISUAL_GUIDE.md +++ b/docs/PR_VISUAL_GUIDE.md @@ -6,6 +6,12 @@ This file lists the manual screenshots to capture after local and real smoke tes Do not fabricate screenshots. If a capability is not available in the test enterprise, keep the placeholder and record the failure in `reports/FEISHU_SMOKE_20260626.md`. +Use the helper to check current screenshot status: + +```powershell +.\scripts\feishu-gitlink-screenshot-check.ps1 +``` + | Screenshot | Expected path | Capture note | | --- | --- | --- | | Feishu bot card in test group | `docs/images/feishu-bot-card.png` | Capture after `+bot-test --send` or `+notify --send` | diff --git a/docs/feishu-integration.md b/docs/feishu-integration.md index 2114dee..1460104 100644 --- a/docs/feishu-integration.md +++ b/docs/feishu-integration.md @@ -53,6 +53,15 @@ Experimental commands use Feishu self-built app OpenAPI and are not part of the Use a Feishu custom group bot for notification cards. +Recommended local setup: + +```powershell +.\scripts\feishu-gitlink-setup.ps1 +.\scripts\feishu-gitlink-env-check.ps1 -Layer stable +``` + +The setup wizard opens Feishu / GitLink pages and stores values only in `.local/feishu-gitlink.env.ps1`. + Environment: ```powershell @@ -288,3 +297,12 @@ docs/FEISHU_ENVIRONMENT.md reports/FEISHU_PERMISSION_MATRIX.md reports/FEISHU_LOCAL_TESTING_GUIDE.md ``` + +Scripted smoke test: + +```powershell +.\scripts\feishu-gitlink-smoke.ps1 -Mode preview +.\scripts\feishu-gitlink-smoke.ps1 -Mode stable +.\scripts\feishu-gitlink-smoke.ps1 -Mode open-platform +.\scripts\feishu-gitlink-smoke.ps1 -Mode all +``` diff --git a/reports/FEISHU_LOCAL_TESTING_GUIDE.md b/reports/FEISHU_LOCAL_TESTING_GUIDE.md index 40d739b..19b4405 100644 --- a/reports/FEISHU_LOCAL_TESTING_GUIDE.md +++ b/reports/FEISHU_LOCAL_TESTING_GUIDE.md @@ -4,7 +4,48 @@ Date: 2026-06-26 This guide verifies the layered Feishu integration without committing secrets. -## 1. Configure GitLink Test Repository +## 1. Run Local Setup Wizard + +```powershell +.\scripts\feishu-gitlink-setup.ps1 +``` + +The setup wizard opens these pages as needed: + +```text +Feishu custom bot documentation +Feishu developer console +Feishu Docs / Wiki +Feishu Base / Bitable +Feishu Tasks +GitLink +``` + +The user logs in and authorizes in the browser. Values are pasted into the local PowerShell prompt, not into ChatGPT. + +The wizard writes only to: + +```text +.local/feishu-gitlink.env.ps1 +``` + +This file is ignored and must not be committed. A tracked empty example is available at: + +```text +.local/feishu-gitlink.env.example.ps1 +``` + +## 2. Check Local Environment + +```powershell +.\scripts\feishu-gitlink-env-check.ps1 -Layer stable +.\scripts\feishu-gitlink-env-check.ps1 -Layer open-platform +.\scripts\feishu-gitlink-env-check.ps1 -Layer all +``` + +The checker prints only redacted values. + +## 3. Configure GitLink Test Repository Manually If Needed ```powershell $env:GITLINK_OWNER="OWNER" @@ -17,7 +58,43 @@ If the current workflow command cannot filter specific PR IDs, keep the PR IDs i $env:GITLINK_TEST_PR_IDS="1,2,3" ``` -## 2. Generate Workflow Report JSON +## 4. Run Scripted Smoke Tests + +Preview only: + +```powershell +.\scripts\feishu-gitlink-smoke.ps1 -Mode preview +``` + +Stable custom bot sends: + +```powershell +.\scripts\feishu-gitlink-smoke.ps1 -Mode stable +``` + +Experimental Open Platform sends: + +```powershell +.\scripts\feishu-gitlink-smoke.ps1 -Mode open-platform +``` + +All available tests: + +```powershell +.\scripts\feishu-gitlink-smoke.ps1 -Mode all +``` + +The smoke runner writes: + +```text +.local/report.json +reports/FEISHU_SMOKE_YYYYMMDD.md +reports/feishu-real-smoke-terminal.log +``` + +The terminal log is ignored and must not be committed after real runs. + +## 5. Generate Workflow Report JSON Manually ```bash gitlink-cli workflow +repo-report \ @@ -28,13 +105,13 @@ gitlink-cli workflow +repo-report \ Windows PowerShell redirection may produce UTF-16 with BOM. The Feishu workflow JSON reader supports UTF-8 and UTF-16 BOM inputs. -## 3. Preview Feishu Notify Card +## 6. Preview Feishu Notify Card ```bash gitlink-cli feishu +notify --from-workflow-json report.json --format json ``` -## 4. Send Feishu Notify Card +## 7. Send Feishu Notify Card ```bash gitlink-cli feishu +notify --from-workflow-json report.json --send --format table @@ -47,50 +124,50 @@ FEISHU_WEBHOOK_URL FEISHU_WEBHOOK_SECRET optional ``` -## 5. Render Weekly Report +## 8. Render Weekly Report ```bash gitlink-cli feishu +weekly-report --from-workflow-json report.json --format markdown ``` -## 6. Send Weekly Report +## 9. Send Weekly Report ```bash gitlink-cli feishu +weekly-report --from-workflow-json report.json --send --format table ``` -## 7. Generate Owner Digest +## 10. Generate Owner Digest ```bash gitlink-cli feishu +owner-digest --from-workflow-json report.json --format markdown ``` -## 8. Send Owner Digest +## 11. Send Owner Digest ```bash gitlink-cli feishu +owner-digest --from-workflow-json report.json --send --format table ``` -## 9. Generate Contributor Digest +## 12. Generate Contributor Digest ```bash gitlink-cli feishu +contributor-digest --from-workflow-json report.json --format markdown ``` -## 10. Send Contributor Digest +## 13. Send Contributor Digest ```bash gitlink-cli feishu +contributor-digest --from-workflow-json report.json --send --format table ``` -## 11. Generate Bitable-Ready Records +## 14. Generate Bitable-Ready Records ```bash gitlink-cli feishu +bitable-schema --tables reports,issues,prs,contributors,tasks --format markdown gitlink-cli feishu +bitable-records --from-workflow-json report.json --format json ``` -## 12. Preview Bitable Sync +## 15. Preview Bitable Sync ```bash gitlink-cli feishu +bitable-sync \ @@ -99,7 +176,7 @@ gitlink-cli feishu +bitable-sync \ --format table ``` -## 13. Execute Bitable Sync +## 16. Execute Bitable Sync ```bash gitlink-cli feishu +bitable-sync \ @@ -122,7 +199,7 @@ FEISHU_CONTRIBUTOR_TABLE_ID optional FEISHU_TASK_TABLE_ID optional ``` -## 14. Preview DocX / Wiki Export +## 17. Preview DocX / Wiki Export ```bash gitlink-cli feishu +doc-export \ @@ -131,7 +208,7 @@ gitlink-cli feishu +doc-export \ --format markdown ``` -## 15. Execute DocX / Wiki Export +## 18. Execute DocX / Wiki Export ```bash gitlink-cli feishu +doc-export \ @@ -141,13 +218,13 @@ gitlink-cli feishu +doc-export \ --format table ``` -## 16. Preview Feishu Tasks +## 19. Preview Feishu Tasks ```bash gitlink-cli feishu +task-preview --from-workflow-json report.json --format markdown ``` -## 17. Create Feishu Tasks +## 20. Create Feishu Tasks ```bash gitlink-cli feishu +task-create --from-workflow-json report.json --send --format table @@ -162,7 +239,15 @@ FEISHU_TASK_PROJECT_ID optional FEISHU_TASK_SECTION_ID optional ``` -## 18. Run Go Tests +## 21. Run Screenshot Check + +```powershell +.\scripts\feishu-gitlink-screenshot-check.ps1 +``` + +The script lists missing screenshots. It does not fabricate images. + +## 22. Run Go Tests ```bash gofmt -w shortcuts/feishu @@ -172,7 +257,7 @@ go test ./shortcuts go test ./... ``` -## 19. Capture Evidence +## 23. Capture Evidence Capture terminal logs and screenshots listed in `docs/PR_VISUAL_GUIDE.md`. diff --git a/reports/FEISHU_SMOKE_20260626.md b/reports/FEISHU_SMOKE_20260626.md index ab760e1..2acba26 100644 --- a/reports/FEISHU_SMOKE_20260626.md +++ b/reports/FEISHU_SMOKE_20260626.md @@ -1,6 +1,6 @@ -# Feishu Smoke Report +# Feishu Smoke Report -Date: 2026-06-26 +Date: 2026-06-26 16:29:18 +08:00 ## Branch @@ -11,23 +11,17 @@ feat/feishu-export-clean ## Commit ```text -working tree smoke before final implementation commit; base HEAD before this implementation: bcdab0b +9255518304e1a6b0fba9f9e5eee9bdf4f62d8e04 ``` -## Test Environment +## Mode ```text -Local OS: Windows / PowerShell -Repository: gitlink-cli-feishu-clean -Feishu test enterprise: available only when local environment variables are configured -Real GitLink repo data: public Gitlink/gitlink-cli workflow report generated through gitlink-cli -Previous 3 GitLink PR IDs: not available in current shell; GITLINK_TEST_PR_IDS was not set +preview ``` ## Redacted Environment Presence -This section must record presence only, not raw values: - | Variable | Present? | | --- | --- | | `FEISHU_WEBHOOK_URL` | missing | @@ -35,104 +29,56 @@ This section must record presence only, not raw values: | `FEISHU_APP_ID` | missing | | `FEISHU_APP_SECRET` | missing | | `FEISHU_WIKI_URL` | missing | +| `FEISHU_WIKI_NODE_TOKEN` | missing | +| `FEISHU_FOLDER_TOKEN` | missing | | `FEISHU_BASE_APP_TOKEN` | missing | | `FEISHU_REPORT_TABLE_ID` | missing | | `FEISHU_ISSUE_TABLE_ID` | missing | | `FEISHU_PR_TABLE_ID` | missing | +| `FEISHU_CONTRIBUTOR_TABLE_ID` | missing | +| `FEISHU_TASK_TABLE_ID` | missing | | `FEISHU_TASK_PROJECT_ID` | missing | +| `FEISHU_TASK_SECTION_ID` | missing | | `GITLINK_OWNER` | missing | | `GITLINK_REPO` | missing | | `GITLINK_TEST_PR_IDS` | missing | +| `GITLINK_TOKEN` | missing | -## Commands Run So Far +## Results -```bash -go run . feishu --help -go run . feishu +owner-digest --help -go run . feishu +bitable-sync --help -go run . feishu +task-create --help - -go run . feishu +owner-digest --from-workflow-json shortcuts/workflow/testdata/repo_report.json --format table -go run . feishu +contributor-digest --from-workflow-json shortcuts/workflow/testdata/repo_report.json --format table -go run . feishu +bitable-records --from-workflow-json shortcuts/workflow/testdata/repo_report.json --tables reports,issues,prs,contributors,tasks --format table -go run . feishu +bitable-sync --from-workflow-json shortcuts/workflow/testdata/repo_report.json --tables reports,tasks --format table -go run . feishu +task-preview --from-workflow-json shortcuts/workflow/testdata/repo_report.json --format table - -$report = Join-Path $env:TEMP 'gitlink-feishu-report-20260626.json' -go run . workflow +repo-report --owner Gitlink --repo gitlink-cli --format json | Set-Content -Encoding utf8 $report -go run . feishu +notify --from-workflow-json $report --format table -go run . feishu +owner-digest --from-workflow-json $report --format table -go run . feishu +contributor-digest --from-workflow-json $report --format table -go run . feishu +bitable-records --from-workflow-json $report --tables reports,issues,prs,contributors,tasks --format table -go run . feishu +task-preview --from-workflow-json $report --format table -go run . feishu +bitable-sync --from-workflow-json $report --tables reports,issues,prs,tasks --format table -go run . feishu +doc-export --from-workflow-json $report --format table - -gofmt -w shortcuts/feishu -go test ./shortcuts/feishu -go test ./shortcuts/workflow -go test ./shortcuts -go test ./... -``` - -## Outputs Summary - -| Step | Result | Notes | +| Command | Result | Details | | --- | --- | --- | -| `feishu --help` | pass | new owner/contributor digest, bitable sync, task preview/create commands visible | -| owner digest preview | pass | role summary generated | -| contributor digest preview | pass | role summary generated | -| bitable records preview | pass | reports/issues/prs/contributors/tasks generated | -| bitable sync preview | pass | preview only, no OpenAPI call | -| task preview | pass | task candidates generated | -| Feishu unit/mock tests | pass | `go test ./shortcuts/feishu` | -| workflow tests | pass | `go test ./shortcuts/workflow` | -| shortcuts tests | pass | `go test ./shortcuts` | -| full repository tests | pass | `go test ./...` | -| public GitLink repo report | pass | `Gitlink/gitlink-cli` report generated in temp directory | -| public GitLink notify preview | pass | preview only, no webhook call | -| public GitLink owner digest | pass | risk/score summary generated | -| public GitLink contributor digest | pass | role-oriented summary generated | -| public GitLink Bitable records | pass | reports/issues/prs/contributors/tasks generated | -| public GitLink Bitable sync preview | pass | preview only, table IDs missing by design | -| public GitLink DocX/Wiki preview | pass | preview only, no Open Platform call | +| feishu help | pass | exit=0 | +| feishu +owner-digest help | pass | exit=0 | +| feishu +contributor-digest help | pass | exit=0 | +| feishu +bitable-sync help | pass | exit=0 | +| feishu +task-preview help | pass | exit=0 | +| feishu +task-create help | pass | exit=0 | +| workflow +repo-report | pass | report=.local/report.json; owner=Gitlink; repo=gitlink-cli | +| notify preview | pass | exit=0 | +| weekly report preview | pass | exit=0 | +| owner digest preview | pass | exit=0 | +| contributor digest preview | pass | exit=0 | +| bitable records preview | pass | exit=0 | +| task preview | pass | exit=0 | -## Real Feishu Webhook Result +## Notes -```text -not executed: FEISHU_WEBHOOK_URL was not present in the current shell. +- No .local/feishu-gitlink.env.ps1 file found. Preview smoke can run with public fallback data; real sends are skipped. +- GITLINK_OWNER/GITLINK_REPO were missing. Preview smoke used public Gitlink/gitlink-cli as a fallback. + +## Terminal Log + +Local redacted terminal log: `reports/feishu-real-smoke-terminal.log` + +This log file is ignored and should not be committed after real runs. + +## Screenshot Checklist + +Run: + +```powershell +.\scripts\feishu-gitlink-screenshot-check.ps1 ``` -## DocX / Wiki Result - -```text -not executed: FEISHU_APP_ID, FEISHU_APP_SECRET, and document target variables were not present in the current shell. -Preview passed with public GitLink report. -``` - -## Bitable Sync Result - -```text -not executed: FEISHU_APP_ID, FEISHU_APP_SECRET, FEISHU_BASE_APP_TOKEN, and table IDs were not present in the current shell. -Preview passed with public GitLink report. -``` - -## Task Creation Result - -```text -not executed: FEISHU_APP_ID and FEISHU_APP_SECRET were not present in the current shell. -Task preview passed with public GitLink report. -``` - -## Failure Diagnostics - -```text -None from local preview, public GitLink read smoke, and unit/mock tests. -Real Open Platform failures must be recorded with endpoint category, HTTP status or Feishu code when available, redacted target type, likely reason, and required permission. -``` - -## Screenshots Or Terminal Logs - -Expected screenshot paths are listed in `docs/PR_VISUAL_GUIDE.md`. - -Do not fabricate screenshots. +Do not fabricate screenshots. Capture missing images manually after real Feishu runs. diff --git a/scripts/feishu-gitlink-env-check.ps1 b/scripts/feishu-gitlink-env-check.ps1 new file mode 100644 index 0000000..e1b0f5f --- /dev/null +++ b/scripts/feishu-gitlink-env-check.ps1 @@ -0,0 +1,88 @@ +param( + [ValidateSet("stable", "open-platform", "all")] + [string]$Layer = "stable" +) + +$ErrorActionPreference = "Stop" +$RepoRoot = Split-Path -Parent $PSScriptRoot +$LocalEnv = Join-Path $RepoRoot ".local/feishu-gitlink.env.ps1" + +function Redact-Value { + param([string]$Value) + if ([string]::IsNullOrWhiteSpace($Value)) { return "" } + if ($Value.Length -le 8) { return "***" } + return "$($Value.Substring(0, 4))...$($Value.Substring($Value.Length - 4))" +} + +function Show-Var { + param( + [string]$Name, + [bool]$Sensitive = $true + ) + $value = [Environment]::GetEnvironmentVariable($Name) + if ([string]::IsNullOrWhiteSpace($value)) { + Write-Host ("{0}: missing" -f $Name) + return $false + } + if ($Sensitive) { + Write-Host ("{0}: set ({1})" -f $Name, (Redact-Value $value)) + } else { + Write-Host ("{0}: set ({1})" -f $Name, $value) + } + return $true +} + +function Test-Group { + param( + [string]$Title, + [string[]]$Names, + [string[]]$Optional = @(), + [string[]]$NonSensitive = @() + ) + Write-Host "" + Write-Host "[$Title]" + $missingRequired = @() + foreach ($name in $Names) { + $isOptional = $Optional -contains $name + $isSensitive = -not ($NonSensitive -contains $name) + $present = Show-Var -Name $name -Sensitive:$isSensitive + if (-not $present -and -not $isOptional) { + $missingRequired += $name + } + } + return $missingRequired +} + +if (Test-Path $LocalEnv) { + . $LocalEnv + Write-Host "Loaded local env: .local/feishu-gitlink.env.ps1" +} else { + Write-Host "No local env file found. Run scripts/feishu-gitlink-setup.ps1 or copy .local/feishu-gitlink.env.example.ps1." +} + +$allMissing = @() + +if ($Layer -eq "stable" -or $Layer -eq "all") { + $allMissing += Test-Group -Title "Stable webhook" -Names @("FEISHU_WEBHOOK_URL", "FEISHU_WEBHOOK_SECRET") -Optional @("FEISHU_WEBHOOK_SECRET") +} + +if ($Layer -eq "open-platform" -or $Layer -eq "all") { + $allMissing += Test-Group -Title "Open Platform app" -Names @("FEISHU_APP_ID", "FEISHU_APP_SECRET") + $allMissing += Test-Group -Title "DocX / Wiki" -Names @("FEISHU_WIKI_URL", "FEISHU_WIKI_NODE_TOKEN", "FEISHU_FOLDER_TOKEN") -Optional @("FEISHU_WIKI_URL", "FEISHU_WIKI_NODE_TOKEN", "FEISHU_FOLDER_TOKEN") + $allMissing += Test-Group -Title "Base / Bitable" -Names @("FEISHU_BASE_APP_TOKEN", "FEISHU_REPORT_TABLE_ID", "FEISHU_ISSUE_TABLE_ID", "FEISHU_PR_TABLE_ID", "FEISHU_CONTRIBUTOR_TABLE_ID", "FEISHU_TASK_TABLE_ID") -Optional @("FEISHU_CONTRIBUTOR_TABLE_ID", "FEISHU_TASK_TABLE_ID") + $allMissing += Test-Group -Title "Feishu Task" -Names @("FEISHU_TASK_PROJECT_ID", "FEISHU_TASK_SECTION_ID") -Optional @("FEISHU_TASK_PROJECT_ID", "FEISHU_TASK_SECTION_ID") +} + +if ($Layer -eq "all") { + $allMissing += Test-Group -Title "GitLink test input" -Names @("GITLINK_OWNER", "GITLINK_REPO", "GITLINK_TEST_PR_IDS", "GITLINK_TOKEN") -Optional @("GITLINK_TEST_PR_IDS", "GITLINK_TOKEN") -NonSensitive @("GITLINK_OWNER", "GITLINK_REPO", "GITLINK_TEST_PR_IDS") +} + +if ($allMissing.Count -gt 0) { + Write-Host "" + Write-Host "Missing required values for layer '$Layer': $($allMissing -join ', ')" + exit 1 +} + +Write-Host "" +Write-Host "Layer '$Layer' is ready." +exit 0 diff --git a/scripts/feishu-gitlink-screenshot-check.ps1 b/scripts/feishu-gitlink-screenshot-check.ps1 new file mode 100644 index 0000000..957b728 --- /dev/null +++ b/scripts/feishu-gitlink-screenshot-check.ps1 @@ -0,0 +1,35 @@ +$ErrorActionPreference = "Stop" +$RepoRoot = Split-Path -Parent $PSScriptRoot +$Expected = @( + "docs/images/feishu-bot-card.png", + "docs/images/feishu-weekly-report.png", + "docs/images/feishu-owner-digest.png", + "docs/images/feishu-contributor-digest.png", + "docs/images/feishu-bitable-preview.png", + "docs/images/feishu-bitable-sync.png", + "docs/images/feishu-docx-wiki.png", + "docs/images/feishu-task-create.png", + "docs/images/feishu-smoke-terminal.png", + "docs/images/feishu-env-redacted.png" +) + +$missing = @() +foreach ($relative in $Expected) { + $path = Join-Path $RepoRoot $relative + if (Test-Path $path) { + Write-Host "Found screenshot: $relative" + } else { + Write-Host "Missing screenshot: $relative" + Write-Host "Open Feishu or terminal and capture this screenshot manually." + $missing += $relative + } +} + +if ($missing.Count -gt 0) { + Write-Host "" + Write-Host "Missing screenshots: $($missing.Count)" + exit 1 +} + +Write-Host "All expected screenshots are present." +exit 0 diff --git a/scripts/feishu-gitlink-setup.ps1 b/scripts/feishu-gitlink-setup.ps1 new file mode 100644 index 0000000..476762a --- /dev/null +++ b/scripts/feishu-gitlink-setup.ps1 @@ -0,0 +1,199 @@ +$ErrorActionPreference = "Stop" +$RepoRoot = Split-Path -Parent $PSScriptRoot +$LocalDir = Join-Path $RepoRoot ".local" +$LocalEnv = Join-Path $LocalDir "feishu-gitlink.env.ps1" + +function Redact { + param([string]$Value) + if ([string]::IsNullOrWhiteSpace($Value)) { return "missing" } + if ($Value.Length -le 8) { return "***" } + return "$($Value.Substring(0, 4))...$($Value.Substring($Value.Length - 4))" +} + +function Escape-PSString { + param([string]$Value) + if ($null -eq $Value) { return "" } + return $Value.Replace('`', '``').Replace('"', '`"') +} + +function SecureString-ToPlainText { + param([System.Security.SecureString]$Secure) + if ($null -eq $Secure) { return "" } + $ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure) + try { + return [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr) + } finally { + if ($ptr -ne [IntPtr]::Zero) { + [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr) + } + } +} + +function Read-OptionalValue { + param( + [string]$Name, + [string]$CurrentValue, + [string]$Hint + ) + $currentLabel = if ([string]::IsNullOrWhiteSpace($CurrentValue)) { "empty" } else { Redact $CurrentValue } + Write-Host "" + Write-Host "$Name ($currentLabel)" + if ($Hint) { Write-Host $Hint } + $value = Read-Host "Enter value, or press Enter to keep current" + if ([string]::IsNullOrWhiteSpace($value)) { return $CurrentValue } + return $value.Trim() +} + +function Read-SecretValue { + param( + [string]$Name, + [string]$CurrentValue, + [string]$Hint + ) + $currentLabel = if ([string]::IsNullOrWhiteSpace($CurrentValue)) { "empty" } else { "set" } + Write-Host "" + Write-Host "$Name ($currentLabel)" + if ($Hint) { Write-Host $Hint } + $secure = Read-Host "Enter secret, or press Enter to keep current" -AsSecureString + $plain = SecureString-ToPlainText $secure + if ([string]::IsNullOrWhiteSpace($plain)) { return $CurrentValue } + return $plain.Trim() +} + +function Open-Url { + param( + [string]$Url, + [string]$Reason + ) + Write-Host "" + Write-Host "Opening: $Reason" + Write-Host $Url + Start-Process $Url +} + +function Pause-User { + param([string]$Message) + [void](Read-Host $Message) +} + +function Env { + param([string]$Name) + return [Environment]::GetEnvironmentVariable($Name) +} + +function Missing { + param([string[]]$Names) + foreach ($name in $Names) { + if ([string]::IsNullOrWhiteSpace((Env $name))) { return $true } + } + return $false +} + +New-Item -ItemType Directory -Force -Path $LocalDir | Out-Null +if (Test-Path $LocalEnv) { + . $LocalEnv + Write-Host "Loaded existing local env: .local/feishu-gitlink.env.ps1" +} + +Write-Host "This setup writes values only to .local/feishu-gitlink.env.ps1." +Write-Host "Do not paste secrets into chat or tracked docs." + +if (Missing @("FEISHU_WEBHOOK_URL")) { + Open-Url "https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot" "Feishu custom bot guide" + Pause-User "Add a custom bot to your Feishu test group and copy the webhook URL. Press Enter when ready." + $env:FEISHU_WEBHOOK_URL = Read-OptionalValue "FEISHU_WEBHOOK_URL" (Env "FEISHU_WEBHOOK_URL") "Used by +bot-test, +notify, +weekly-report, +owner-digest, and +contributor-digest." + $env:FEISHU_WEBHOOK_SECRET = Read-SecretValue "FEISHU_WEBHOOK_SECRET" (Env "FEISHU_WEBHOOK_SECRET") "Optional signing secret from the custom bot security settings." +} + +if (Missing @("FEISHU_APP_ID", "FEISHU_APP_SECRET")) { + Open-Url "https://open.feishu.cn/app" "Feishu developer console" + Pause-User "Create/open a self-built app, enable required scopes, and copy app_id/app_secret. Press Enter when ready." + $env:FEISHU_APP_ID = Read-OptionalValue "FEISHU_APP_ID" (Env "FEISHU_APP_ID") "Used by experimental +doc-export, +bitable-sync, and +task-create." + $env:FEISHU_APP_SECRET = Read-SecretValue "FEISHU_APP_SECRET" (Env "FEISHU_APP_SECRET") "Self-built app secret." +} + +if (Missing @("FEISHU_WIKI_URL", "FEISHU_WIKI_NODE_TOKEN", "FEISHU_FOLDER_TOKEN")) { + Open-Url "https://www.feishu.cn/" "Feishu Docs / Wiki" + Pause-User "Open your target Wiki/Doc page or folder and copy the URL/token. Press Enter when ready." + $env:FEISHU_WIKI_URL = Read-OptionalValue "FEISHU_WIKI_URL" (Env "FEISHU_WIKI_URL") "Existing Wiki or Doc URL for +doc-export." + $env:FEISHU_WIKI_NODE_TOKEN = Read-OptionalValue "FEISHU_WIKI_NODE_TOKEN" (Env "FEISHU_WIKI_NODE_TOKEN") "Optional. Usually parsed from FEISHU_WIKI_URL." + $env:FEISHU_FOLDER_TOKEN = Read-OptionalValue "FEISHU_FOLDER_TOKEN" (Env "FEISHU_FOLDER_TOKEN") "Optional. Used when creating a new DocX in a folder." +} + +if (Missing @("FEISHU_BASE_APP_TOKEN", "FEISHU_REPORT_TABLE_ID", "FEISHU_ISSUE_TABLE_ID", "FEISHU_PR_TABLE_ID")) { + Open-Url "https://www.feishu.cn/" "Feishu Base / Bitable" + Pause-User "Open/create the Base for reports, issues, prs, contributors, and tasks. Press Enter when table IDs are ready." + Write-Host "Expected tables: reports, issues, prs, contributors, tasks." + Write-Host "Each selected table should contain at least unique_key and repository." + $env:FEISHU_BASE_APP_TOKEN = Read-OptionalValue "FEISHU_BASE_APP_TOKEN" (Env "FEISHU_BASE_APP_TOKEN") "Base app token." + $env:FEISHU_REPORT_TABLE_ID = Read-OptionalValue "FEISHU_REPORT_TABLE_ID" (Env "FEISHU_REPORT_TABLE_ID") "Reports table ID." + $env:FEISHU_ISSUE_TABLE_ID = Read-OptionalValue "FEISHU_ISSUE_TABLE_ID" (Env "FEISHU_ISSUE_TABLE_ID") "Issues table ID." + $env:FEISHU_PR_TABLE_ID = Read-OptionalValue "FEISHU_PR_TABLE_ID" (Env "FEISHU_PR_TABLE_ID") "Pull request table ID." + $env:FEISHU_CONTRIBUTOR_TABLE_ID = Read-OptionalValue "FEISHU_CONTRIBUTOR_TABLE_ID" (Env "FEISHU_CONTRIBUTOR_TABLE_ID") "Optional contributor table ID." + $env:FEISHU_TASK_TABLE_ID = Read-OptionalValue "FEISHU_TASK_TABLE_ID" (Env "FEISHU_TASK_TABLE_ID") "Optional task candidate table ID." +} + +if (Missing @("FEISHU_TASK_PROJECT_ID", "FEISHU_TASK_SECTION_ID")) { + Open-Url "https://www.feishu.cn/" "Feishu Tasks" + Pause-User "Open the Feishu Task project/section if needed. Press Enter when IDs are ready." + $env:FEISHU_TASK_PROJECT_ID = Read-OptionalValue "FEISHU_TASK_PROJECT_ID" (Env "FEISHU_TASK_PROJECT_ID") "Optional. Some Task API paths may not require it." + $env:FEISHU_TASK_SECTION_ID = Read-OptionalValue "FEISHU_TASK_SECTION_ID" (Env "FEISHU_TASK_SECTION_ID") "Optional." +} + +if (Missing @("GITLINK_OWNER", "GITLINK_REPO")) { + Open-Url "https://www.gitlink.org.cn/" "GitLink" + Pause-User "Open the target GitLink repository and the previous 3 PRs. Press Enter when ready." + $env:GITLINK_OWNER = Read-OptionalValue "GITLINK_OWNER" (Env "GITLINK_OWNER") "Repository owner, for example Gitlink." + $env:GITLINK_REPO = Read-OptionalValue "GITLINK_REPO" (Env "GITLINK_REPO") "Repository name, for example gitlink-cli." + $env:GITLINK_TEST_PR_IDS = Read-OptionalValue "GITLINK_TEST_PR_IDS" (Env "GITLINK_TEST_PR_IDS") "Comma-separated PR IDs for smoke report references." + $env:GITLINK_TOKEN = Read-SecretValue "GITLINK_TOKEN" (Env "GITLINK_TOKEN") "Optional if gitlink-cli is already logged in." +} + +if (-not [string]::IsNullOrWhiteSpace($env:GITLINK_OWNER) -and -not [string]::IsNullOrWhiteSpace($env:GITLINK_REPO)) { + Open-Url "https://www.gitlink.org.cn/$env:GITLINK_OWNER/$env:GITLINK_REPO" "Target GitLink repository" + if (-not [string]::IsNullOrWhiteSpace($env:GITLINK_TEST_PR_IDS)) { + Write-Host "GITLINK_TEST_PR_IDS set: $env:GITLINK_TEST_PR_IDS" + Write-Host "Verify the PR page URL pattern manually if needed." + } +} + +$vars = @( + "FEISHU_WEBHOOK_URL", + "FEISHU_WEBHOOK_SECRET", + "FEISHU_APP_ID", + "FEISHU_APP_SECRET", + "FEISHU_WIKI_URL", + "FEISHU_WIKI_NODE_TOKEN", + "FEISHU_FOLDER_TOKEN", + "FEISHU_BASE_APP_TOKEN", + "FEISHU_REPORT_TABLE_ID", + "FEISHU_ISSUE_TABLE_ID", + "FEISHU_PR_TABLE_ID", + "FEISHU_CONTRIBUTOR_TABLE_ID", + "FEISHU_TASK_TABLE_ID", + "FEISHU_TASK_PROJECT_ID", + "FEISHU_TASK_SECTION_ID", + "GITLINK_OWNER", + "GITLINK_REPO", + "GITLINK_TEST_PR_IDS", + "GITLINK_TOKEN" +) + +$lines = @( + "# Local Feishu/GitLink smoke-test environment.", + "# Generated by scripts/feishu-gitlink-setup.ps1.", + "# Do not commit this file." +) +foreach ($name in $vars) { + $value = [Environment]::GetEnvironmentVariable($name) + $lines += ('$' + ('env:{0}="{1}"' -f $name, (Escape-PSString $value))) +} +$lines | Set-Content -LiteralPath $LocalEnv -Encoding utf8 + +Write-Host "" +Write-Host "Saved local env: .local/feishu-gitlink.env.ps1" +Write-Host "Redacted summary:" +foreach ($name in $vars) { + $value = [Environment]::GetEnvironmentVariable($name) + Write-Host ("{0}: {1}" -f $name, (Redact $value)) +} diff --git a/scripts/feishu-gitlink-smoke.ps1 b/scripts/feishu-gitlink-smoke.ps1 new file mode 100644 index 0000000..80587a1 --- /dev/null +++ b/scripts/feishu-gitlink-smoke.ps1 @@ -0,0 +1,336 @@ +param( + [ValidateSet("preview", "stable", "open-platform", "all")] + [string]$Mode = "preview" +) + +$ErrorActionPreference = "Stop" +$RepoRoot = Split-Path -Parent $PSScriptRoot +$LocalDir = Join-Path $RepoRoot ".local" +$LocalEnv = Join-Path $LocalDir "feishu-gitlink.env.ps1" +$ReportJSON = Join-Path $LocalDir "report.json" +$TerminalLog = Join-Path $RepoRoot "reports/feishu-real-smoke-terminal.log" +$DateStamp = Get-Date -Format "yyyyMMdd" +$SmokeReport = Join-Path $RepoRoot "reports/FEISHU_SMOKE_$DateStamp.md" +$Results = New-Object System.Collections.Generic.List[object] +$Notes = New-Object System.Collections.Generic.List[string] + +function Env { + param([string]$Name) + return [Environment]::GetEnvironmentVariable($Name) +} + +function Has-Env { + param([string[]]$Names) + foreach ($name in $Names) { + if ([string]::IsNullOrWhiteSpace((Env $name))) { return $false } + } + return $true +} + +function Redact-Value { + param([string]$Value) + if ([string]::IsNullOrWhiteSpace($Value)) { return "" } + if ($Value.Length -le 8) { return "***" } + return "$($Value.Substring(0, 4))...$($Value.Substring($Value.Length - 4))" +} + +function Redact-Text { + param([string]$Text) + if ($null -eq $Text) { return "" } + $redacted = $Text + $names = @( + "FEISHU_WEBHOOK_URL", + "FEISHU_WEBHOOK_SECRET", + "FEISHU_APP_ID", + "FEISHU_APP_SECRET", + "FEISHU_WIKI_URL", + "FEISHU_WIKI_NODE_TOKEN", + "FEISHU_FOLDER_TOKEN", + "FEISHU_BASE_APP_TOKEN", + "FEISHU_REPORT_TABLE_ID", + "FEISHU_ISSUE_TABLE_ID", + "FEISHU_PR_TABLE_ID", + "FEISHU_CONTRIBUTOR_TABLE_ID", + "FEISHU_TASK_TABLE_ID", + "FEISHU_TASK_PROJECT_ID", + "FEISHU_TASK_SECTION_ID", + "GITLINK_TOKEN" + ) + foreach ($name in $names) { + $value = Env $name + if (-not [string]::IsNullOrWhiteSpace($value)) { + $redacted = [regex]::Replace($redacted, [regex]::Escape($value), (Redact-Value $value)) + } + } + $redacted = [regex]::Replace($redacted, 'tenant_access_token"\s*:\s*"[^"]+', 'tenant_access_token":"REDACTED') + return $redacted +} + +function Add-Result { + param( + [string]$Name, + [string]$Status, + [string]$Details + ) + $Results.Add([pscustomobject]@{ + Name = $Name + Status = $Status + Details = (Redact-Text $Details) + }) | Out-Null +} + +function Write-Log { + param([string]$Text) + Add-Content -LiteralPath $TerminalLog -Value (Redact-Text $Text) +} + +function Invoke-Cmd { + param( + [string]$Name, + [string[]]$CommandArgs, + [bool]$Required = $false + ) + $display = $CommandArgs -join " " + Write-Host "RUN: $Name" + Write-Log "" + Write-Log "## $Name" + Write-Log "COMMAND: $display" + $exe = $CommandArgs[0] + $rest = @() + if ($CommandArgs.Count -gt 1) { + $rest = $CommandArgs[1..($CommandArgs.Count - 1)] + } + $output = & $exe @rest 2>&1 | Out-String + $exit = $LASTEXITCODE + Write-Log $output + if ($exit -eq 0) { + Add-Result $Name "pass" "exit=0" + } else { + Add-Result $Name "fail" ("exit={0}; {1}" -f $exit, (($output -split "`r?`n" | Select-Object -First 4) -join " ")) + if ($Required) { + throw "$Name failed with exit $exit" + } + } +} + +function Invoke-ReportGeneration { + $owner = Env "GITLINK_OWNER" + $repo = Env "GITLINK_REPO" + if ([string]::IsNullOrWhiteSpace($owner) -or [string]::IsNullOrWhiteSpace($repo)) { + $owner = "Gitlink" + $repo = "gitlink-cli" + $Notes.Add("GITLINK_OWNER/GITLINK_REPO were missing. Preview smoke used public Gitlink/gitlink-cli as a fallback.") | Out-Null + } + if (-not [string]::IsNullOrWhiteSpace((Env "GITLINK_TEST_PR_IDS"))) { + $Notes.Add("GITLINK_TEST_PR_IDS was provided, but workflow +repo-report currently does not support explicit PR ID filtering. The smoke test used the real repository report instead.") | Out-Null + } + Write-Host "Generating workflow report for $owner/$repo" + Write-Log "" + Write-Log "## Generate workflow report" + $output = & go run . workflow +repo-report --owner $owner --repo $repo --format json 2>&1 | Out-String + $exit = $LASTEXITCODE + if ($exit -ne 0) { + Write-Log $output + Add-Result "workflow +repo-report" "fail" ("exit={0}; {1}" -f $exit, (($output -split "`r?`n" | Select-Object -First 4) -join " ")) + throw "workflow +repo-report failed" + } + $output | Set-Content -LiteralPath $ReportJSON -Encoding utf8 + Write-Log "Report written to .local/report.json" + Add-Result "workflow +repo-report" "pass" "report=.local/report.json; owner=$owner; repo=$repo" +} + +function Add-Skip { + param([string]$Name, [string]$Reason) + Write-Host "SKIP: $Name - $Reason" + Write-Log "" + Write-Log "## $Name" + Write-Log "SKIP: $Reason" + Add-Result $Name "skip" $Reason +} + +function Env-Status { + param([string]$Name) + if ([string]::IsNullOrWhiteSpace((Env $Name))) { return "missing" } + return "present" +} + +function Escape-Table { + param([string]$Value) + if ($null -eq $Value) { return "" } + return ($Value -replace '\|', '\|' -replace "`r?`n", " ") +} + +function Write-SmokeReport { + $branch = (git branch --show-current | Out-String).Trim() + $commit = (git rev-parse HEAD | Out-String).Trim() + $envNames = @( + "FEISHU_WEBHOOK_URL", + "FEISHU_WEBHOOK_SECRET", + "FEISHU_APP_ID", + "FEISHU_APP_SECRET", + "FEISHU_WIKI_URL", + "FEISHU_WIKI_NODE_TOKEN", + "FEISHU_FOLDER_TOKEN", + "FEISHU_BASE_APP_TOKEN", + "FEISHU_REPORT_TABLE_ID", + "FEISHU_ISSUE_TABLE_ID", + "FEISHU_PR_TABLE_ID", + "FEISHU_CONTRIBUTOR_TABLE_ID", + "FEISHU_TASK_TABLE_ID", + "FEISHU_TASK_PROJECT_ID", + "FEISHU_TASK_SECTION_ID", + "GITLINK_OWNER", + "GITLINK_REPO", + "GITLINK_TEST_PR_IDS", + "GITLINK_TOKEN" + ) + $lines = @( + "# Feishu Smoke Report", + "", + "Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss zzz')", + "", + "## Branch", + "", + '```text', + $branch, + '```', + "", + "## Commit", + "", + '```text', + $commit, + '```', + "", + "## Mode", + "", + '```text', + $Mode, + '```', + "", + "## Redacted Environment Presence", + "", + "| Variable | Present? |", + "| --- | --- |" + ) + foreach ($name in $envNames) { + $lines += ('| `{0}` | {1} |' -f $name, (Env-Status $name)) + } + $lines += @( + "", + "## Results", + "", + "| Command | Result | Details |", + "| --- | --- | --- |" + ) + foreach ($result in $Results) { + $lines += "| $(Escape-Table $result.Name) | $(Escape-Table $result.Status) | $(Escape-Table $result.Details) |" + } + $lines += @( + "", + "## Notes", + "" + ) + if ($Notes.Count -eq 0) { + $lines += "- None." + } else { + foreach ($note in $Notes) { + $lines += "- $(Redact-Text $note)" + } + } + $lines += @( + "", + "## Terminal Log", + "", + 'Local redacted terminal log: `reports/feishu-real-smoke-terminal.log`', + "", + "This log file is ignored and should not be committed after real runs.", + "", + "## Screenshot Checklist", + "", + "Run:", + "", + '```powershell', + ".\scripts\feishu-gitlink-screenshot-check.ps1", + '```', + "", + "Do not fabricate screenshots. Capture missing images manually after real Feishu runs." + ) + $lines | Set-Content -LiteralPath $SmokeReport -Encoding utf8 + Write-Host "Smoke report written: $SmokeReport" +} + +Push-Location $RepoRoot +try { + New-Item -ItemType Directory -Force -Path $LocalDir | Out-Null + New-Item -ItemType Directory -Force -Path (Join-Path $RepoRoot "reports") | Out-Null + if (Test-Path $LocalEnv) { + . $LocalEnv + Write-Host "Loaded local env: .local/feishu-gitlink.env.ps1" + } else { + $Notes.Add("No .local/feishu-gitlink.env.ps1 file found. Preview smoke can run with public fallback data; real sends are skipped.") | Out-Null + } + "# Feishu/GitLink smoke terminal log $(Get-Date -Format o)" | Set-Content -LiteralPath $TerminalLog -Encoding utf8 + + $helpCommands = @( + "+owner-digest", + "+contributor-digest", + "+bitable-sync", + "+task-preview", + "+task-create" + ) + Invoke-Cmd "feishu help" @("go", "run", ".", "feishu", "--help") $true + foreach ($command in $helpCommands) { + Invoke-Cmd "feishu $command help" @("go", "run", ".", "feishu", $command, "--help") $true + } + + Invoke-ReportGeneration + + $runPreview = $Mode -in @("preview", "stable", "open-platform", "all") + $runStable = $Mode -in @("stable", "all") + $runOpenPlatform = $Mode -in @("open-platform", "all") + + if ($runPreview) { + Invoke-Cmd "notify preview" @("go", "run", ".", "feishu", "+notify", "--from-workflow-json", $ReportJSON, "--format", "table") $true + Invoke-Cmd "weekly report preview" @("go", "run", ".", "feishu", "+weekly-report", "--from-workflow-json", $ReportJSON, "--format", "markdown") $true + Invoke-Cmd "owner digest preview" @("go", "run", ".", "feishu", "+owner-digest", "--from-workflow-json", $ReportJSON, "--format", "table") $true + Invoke-Cmd "contributor digest preview" @("go", "run", ".", "feishu", "+contributor-digest", "--from-workflow-json", $ReportJSON, "--format", "table") $true + Invoke-Cmd "bitable records preview" @("go", "run", ".", "feishu", "+bitable-records", "--from-workflow-json", $ReportJSON, "--tables", "reports,issues,prs,contributors,tasks", "--format", "table") $true + Invoke-Cmd "task preview" @("go", "run", ".", "feishu", "+task-preview", "--from-workflow-json", $ReportJSON, "--format", "table") $true + } + + if ($runStable) { + if (Has-Env @("FEISHU_WEBHOOK_URL")) { + Invoke-Cmd "bot-test send" @("go", "run", ".", "feishu", "+bot-test", "--send", "--format", "table") $false + Invoke-Cmd "notify send" @("go", "run", ".", "feishu", "+notify", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + Invoke-Cmd "weekly report send" @("go", "run", ".", "feishu", "+weekly-report", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + Invoke-Cmd "owner digest send" @("go", "run", ".", "feishu", "+owner-digest", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + Invoke-Cmd "contributor digest send" @("go", "run", ".", "feishu", "+contributor-digest", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + } else { + Add-Skip "stable webhook send" "FEISHU_WEBHOOK_URL missing" + } + } + + if ($runOpenPlatform) { + if (Has-Env @("FEISHU_APP_ID", "FEISHU_APP_SECRET") -and (Has-Env @("FEISHU_WIKI_URL") -or Has-Env @("FEISHU_WIKI_NODE_TOKEN") -or Has-Env @("FEISHU_FOLDER_TOKEN"))) { + Invoke-Cmd "doc-export send" @("go", "run", ".", "feishu", "+doc-export", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + } else { + Add-Skip "doc-export send" "missing FEISHU_APP_ID/FEISHU_APP_SECRET or DocX/Wiki target" + } + + if (Has-Env @("FEISHU_APP_ID", "FEISHU_APP_SECRET", "FEISHU_BASE_APP_TOKEN", "FEISHU_REPORT_TABLE_ID", "FEISHU_ISSUE_TABLE_ID", "FEISHU_PR_TABLE_ID")) { + Invoke-Cmd "bitable-sync send" @("go", "run", ".", "feishu", "+bitable-sync", "--from-workflow-json", $ReportJSON, "--tables", "reports,issues,prs,contributors,tasks", "--send", "--format", "table") $false + } else { + Add-Skip "bitable-sync send" "missing app/base/table variables" + } + + if (Has-Env @("FEISHU_APP_ID", "FEISHU_APP_SECRET")) { + Invoke-Cmd "task-create send" @("go", "run", ".", "feishu", "+task-create", "--from-workflow-json", $ReportJSON, "--send", "--format", "table") $false + } else { + Add-Skip "task-create send" "missing FEISHU_APP_ID/FEISHU_APP_SECRET" + } + } + + Write-SmokeReport +} finally { + Pop-Location +}