test(feishu): add local setup and smoke scripts
This commit is contained in:
parent
8bcc8607f5
commit
73da46c143
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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=""
|
||||
10
README.md
10
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,
|
||||
|
|
|
|||
|
|
@ -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 直接调用:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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` |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
Loading…
Reference in New Issue