refactor(setup): consolidate prettier config and streamline CI
- Replace scattered .prettierignore files with a single root config - Add scripts/ci.js to orchestrate lint, format, typecheck, commitlint, and build - Simplify ci.yml to use ci.js and npm ci - Apply prettier formatting to docs, locales, and HTML files
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: pre-impl-discussion
|
name: pre-impl-discussion
|
||||||
description: "Conduct a thorough pre-implementation discussion before making significant changes. Use when the user wants to discuss, plan, or evaluate a change before implementing it — especially when they say words like 'discuss', 'evaluate', 'plan', or 'let's talk about'."
|
description: "Conduct a thorough pre-implementation discussion before making significant changes. Use when the user wants to discuss, plan, or evaluate a change before implementing it — especially when they say words like 'discuss', 'evaluate', 'plan', or 'let's talk about'."
|
||||||
argument-hint: "Describe the change to evaluate"
|
argument-hint: 'Describe the change to evaluate'
|
||||||
---
|
---
|
||||||
|
|
||||||
# Pre-Implementation Discussion
|
# Pre-Implementation Discussion
|
||||||
@@ -40,6 +40,7 @@ Do NOT skip this step. Do NOT rely on assumptions about what "most projects" do.
|
|||||||
- **Search in parallel** to save time — batch independent queries
|
- **Search in parallel** to save time — batch independent queries
|
||||||
|
|
||||||
Common pitfalls:
|
Common pitfalls:
|
||||||
|
|
||||||
- Assuming compatibility without checking actual version constraints
|
- Assuming compatibility without checking actual version constraints
|
||||||
- Confusing roadmap/aspirations with actual released state
|
- Confusing roadmap/aspirations with actual released state
|
||||||
- Missing transitive constraints (a dependency of a dependency)
|
- Missing transitive constraints (a dependency of a dependency)
|
||||||
@@ -53,6 +54,7 @@ Share a **brief** assessment. Tables work well for comparisons. Highlight **bloc
|
|||||||
Surface the decisions the user needs to make. Present them as clear choices with trade-offs, not as a recommendation monologue.
|
Surface the decisions the user needs to make. Present them as clear choices with trade-offs, not as a recommendation monologue.
|
||||||
|
|
||||||
For each decision point:
|
For each decision point:
|
||||||
|
|
||||||
- What are the options? (2-3 max)
|
- What are the options? (2-3 max)
|
||||||
- What does each option cost or give up?
|
- What does each option cost or give up?
|
||||||
- What's your lean and why? (one sentence)
|
- What's your lean and why? (one sentence)
|
||||||
@@ -66,6 +68,7 @@ The user will ask follow-up questions, raise concerns, or challenge assumptions.
|
|||||||
- **Update your mental model** based on user feedback
|
- **Update your mental model** based on user feedback
|
||||||
|
|
||||||
Common mistakes in this phase:
|
Common mistakes in this phase:
|
||||||
|
|
||||||
- Repeating the full plan after every small clarification
|
- Repeating the full plan after every small clarification
|
||||||
- Answering a narrow question with a broad redesign
|
- Answering a narrow question with a broad redesign
|
||||||
- Treating user questions as confirmation to proceed
|
- Treating user questions as confirmation to proceed
|
||||||
@@ -84,6 +87,7 @@ Keep it terse. Tables over paragraphs. No explanations the user already heard du
|
|||||||
### 7. Wait for Confirmation
|
### 7. Wait for Confirmation
|
||||||
|
|
||||||
After presenting the final plan, **stop and wait**. The user will either:
|
After presenting the final plan, **stop and wait**. The user will either:
|
||||||
|
|
||||||
- Confirm → then (and only then) proceed to implementation
|
- Confirm → then (and only then) proceed to implementation
|
||||||
- Ask more questions → go back to step 5
|
- Ask more questions → go back to step 5
|
||||||
- Modify scope → update the plan and re-present
|
- Modify scope → update the plan and re-present
|
||||||
@@ -91,7 +95,7 @@ After presenting the final plan, **stop and wait**. The user will either:
|
|||||||
## Anti-Patterns
|
## Anti-Patterns
|
||||||
|
|
||||||
| Don't | Do Instead |
|
| Don't | Do Instead |
|
||||||
|-------|------------|
|
| --------------------------------------------------- | ---------------------------------------- |
|
||||||
| Start implementation "to test" without confirmation | Present findings and wait |
|
| Start implementation "to test" without confirmation | Present findings and wait |
|
||||||
| Repeat the full plan in every response | Answer the specific question asked |
|
| Repeat the full plan in every response | Answer the specific question asked |
|
||||||
| Say "X should work" without checking | Say "I need to verify X" and research it |
|
| Say "X should work" without checking | Say "I need to verify X" and research it |
|
||||||
|
|||||||
20
.github/workflows/ci.yml
vendored
20
.github/workflows/ci.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
|
name: CI
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -17,6 +17,8 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v6
|
||||||
@@ -24,18 +26,8 @@ jobs:
|
|||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
# test on default version of npm
|
|
||||||
# - 9.6~10.8 on node@20
|
|
||||||
# - 11.3~11.6 on node@24
|
|
||||||
|
|
||||||
- name: Node and NPM version
|
|
||||||
run: node --version && npm --version
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
|
|
||||||
- name: Lint
|
- name: CI checks
|
||||||
run: npx eslint . && npx prettier --check **/*.ts
|
run: node scripts/ci.js
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: npm run build
|
|
||||||
|
|||||||
8
.prettierignore
Normal file
8
.prettierignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Prompt templates (formatted manually for LLM readability)
|
||||||
|
*prompt.md
|
||||||
|
|
||||||
|
# Generated
|
||||||
|
packages/extension/.wxt
|
||||||
|
|
||||||
|
# Vendored
|
||||||
|
**/components/ui
|
||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -22,7 +22,7 @@
|
|||||||
"packages/*/node_modules": true
|
"packages/*/node_modules": true
|
||||||
},
|
},
|
||||||
"markdownlint.config": {
|
"markdownlint.config": {
|
||||||
// "comment": "Relaxed rules",
|
// Relaxed rules
|
||||||
"default": true,
|
"default": true,
|
||||||
"whitespace": false,
|
"whitespace": false,
|
||||||
"line_length": false,
|
"line_length": false,
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
"ol-prefix": false,
|
"ol-prefix": false,
|
||||||
"no-duplicate-heading": false
|
"no-duplicate-heading": false
|
||||||
},
|
},
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"js/ts.tsdk.path": "node_modules/typescript/lib",
|
"js/ts.tsdk.path": "node_modules/typescript/lib",
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||||
|
|||||||
@@ -16,21 +16,21 @@ appearance, race, religion, or sexual identity and orientation.
|
|||||||
Examples of behavior that contributes to creating a positive environment
|
Examples of behavior that contributes to creating a positive environment
|
||||||
include:
|
include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances
|
advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic
|
- Publishing others' private information, such as a physical or electronic
|
||||||
address, without explicit permission
|
address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
@@ -85,19 +85,19 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.ht
|
|||||||
|
|
||||||
有助于创造正面环境的行为包括但不限于:
|
有助于创造正面环境的行为包括但不限于:
|
||||||
|
|
||||||
* 使用友好和包容性语言
|
- 使用友好和包容性语言
|
||||||
* 尊重不同的观点和经历
|
- 尊重不同的观点和经历
|
||||||
* 耐心地接受建设性批评
|
- 耐心地接受建设性批评
|
||||||
* 关注对社区最有利的事情
|
- 关注对社区最有利的事情
|
||||||
* 友善对待其他社区成员
|
- 友善对待其他社区成员
|
||||||
|
|
||||||
身为参与者不能接受的行为包括但不限于:
|
身为参与者不能接受的行为包括但不限于:
|
||||||
|
|
||||||
* 使用与性有关的言语或是图像,以及不受欢迎的性骚扰
|
- 使用与性有关的言语或是图像,以及不受欢迎的性骚扰
|
||||||
* 捣乱/煽动/造谣的行为或进行侮辱/贬损的评论,人身攻击及政治攻击
|
- 捣乱/煽动/造谣的行为或进行侮辱/贬损的评论,人身攻击及政治攻击
|
||||||
* 公开或私下的骚扰
|
- 公开或私下的骚扰
|
||||||
* 未经许可地发布他人的个人资料,例如住址或是电子地址
|
- 未经许可地发布他人的个人资料,例如住址或是电子地址
|
||||||
* 其他可以被合理地认定为不恰当或者违反职业操守的行为
|
- 其他可以被合理地认定为不恰当或者违反职业操守的行为
|
||||||
|
|
||||||
## 我们的责任
|
## 我们的责任
|
||||||
|
|
||||||
|
|||||||
@@ -106,4 +106,3 @@ this project possible.
|
|||||||
---
|
---
|
||||||
|
|
||||||
**⭐ 如果觉得 PageAgent 有用或有趣,请给项目点个星!**
|
**⭐ 如果觉得 PageAgent 有用或有趣,请给项目点个星!**
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
"postpublish": "npm run postpublish --workspaces --if-present",
|
"postpublish": "npm run postpublish --workspaces --if-present",
|
||||||
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json && tsc --noEmit -p packages/extension/tsconfig.json",
|
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json && tsc --noEmit -p packages/extension/tsconfig.json",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
|
"ci": "node scripts/ci.js",
|
||||||
"cleanup": "rm -rf packages/*/dist && rm -rf packages/*/.output",
|
"cleanup": "rm -rf packages/*/dist && rm -rf packages/*/.output",
|
||||||
"prepare": "husky || true"
|
"prepare": "husky || true"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
system_prompt.md
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
.wxt
|
|
||||||
src/components/ui
|
|
||||||
@@ -42,12 +42,7 @@ localStorage.setItem('PageAgentExtUserAuthToken', 'your-token')
|
|||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type {
|
import type { AgentActivity, AgentStatus, ExecutionResult, HistoricalEvent } from '@page-agent/core'
|
||||||
AgentActivity,
|
|
||||||
AgentStatus,
|
|
||||||
ExecutionResult,
|
|
||||||
HistoricalEvent,
|
|
||||||
} from '@page-agent/core'
|
|
||||||
|
|
||||||
// Wait for extension injection (up to 1 second)
|
// Wait for extension injection (up to 1 second)
|
||||||
async function waitForExtension(timeout = 1000): Promise<boolean> {
|
async function waitForExtension(timeout = 1000): Promise<boolean> {
|
||||||
@@ -91,7 +86,7 @@ Execute one agent task.
|
|||||||
Parameters:
|
Parameters:
|
||||||
|
|
||||||
| Name | Type | Required | Description |
|
| Name | Type | Required | Description |
|
||||||
| ---- | ---- | -------- | ----------- |
|
| -------- | --------------- | -------- | ------------------------------------ |
|
||||||
| `task` | `string` | Yes | Task description |
|
| `task` | `string` | Yes | Task description |
|
||||||
| `config` | `ExecuteConfig` | Yes | LLM settings, options, and callbacks |
|
| `config` | `ExecuteConfig` | Yes | LLM settings, options, and callbacks |
|
||||||
|
|
||||||
@@ -106,12 +101,7 @@ Stop the current task.
|
|||||||
Install `@page-agent/core` for complete types:
|
Install `@page-agent/core` for complete types:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type {
|
import type { AgentActivity, AgentStatus, ExecutionResult, HistoricalEvent } from '@page-agent/core'
|
||||||
AgentActivity,
|
|
||||||
AgentStatus,
|
|
||||||
ExecutionResult,
|
|
||||||
HistoricalEvent,
|
|
||||||
} from '@page-agent/core'
|
|
||||||
|
|
||||||
export interface ExecuteConfig {
|
export interface ExecuteConfig {
|
||||||
baseURL: string
|
baseURL: string
|
||||||
@@ -205,12 +195,7 @@ window.PAGE_AGENT_EXT!.stop()
|
|||||||
If you are not importing `@page-agent/core`, add:
|
If you are not importing `@page-agent/core`, add:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import type {
|
import type { AgentActivity, AgentStatus, ExecutionResult, HistoricalEvent } from '@page-agent/core'
|
||||||
AgentActivity,
|
|
||||||
AgentStatus,
|
|
||||||
ExecutionResult,
|
|
||||||
HistoricalEvent,
|
|
||||||
} from '@page-agent/core'
|
|
||||||
|
|
||||||
interface ExecuteConfig {
|
interface ExecuteConfig {
|
||||||
baseURL: string
|
baseURL: string
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
system_prompt.md
|
|
||||||
@@ -37,7 +37,7 @@ Same format — add the config to the MCP settings of your client.
|
|||||||
## MCP Tools
|
## MCP Tools
|
||||||
|
|
||||||
| Tool | Input | Description |
|
| Tool | Input | Description |
|
||||||
| -------------- | ------------------ | ---------------------------------------------------- |
|
| -------------- | ------------------ | ----------------------------------------------------- |
|
||||||
| `execute_task` | `{ task: string }` | Execute a browser task in natural language. Blocking. |
|
| `execute_task` | `{ task: string }` | Execute a browser task in natural language. Blocking. |
|
||||||
| `get_status` | — | Returns `{ connected, busy }` |
|
| `get_status` | — | Returns `{ connected, busy }` |
|
||||||
| `stop_task` | — | Stop the currently running task. |
|
| `stop_task` | — | Stop the currently running task. |
|
||||||
|
|||||||
@@ -3,7 +3,10 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" href="https://img.alicdn.com/imgextra/i1/O1CN01mRGret1QrKiu7CFJI_!!6000000002029-2-tps-64-64.png" />
|
<link
|
||||||
|
rel="icon"
|
||||||
|
href="https://img.alicdn.com/imgextra/i1/O1CN01mRGret1QrKiu7CFJI_!!6000000002029-2-tps-64-64.png"
|
||||||
|
/>
|
||||||
<title>Page Agent MCP Launcher</title>
|
<title>Page Agent MCP Launcher</title>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
@@ -172,16 +175,26 @@
|
|||||||
If the extension is outdated, please update it to the latest version.
|
If the extension is outdated, please update it to the latest version.
|
||||||
</li>
|
</li>
|
||||||
<li data-i18n="tip_other_browser">
|
<li data-i18n="tip_other_browser">
|
||||||
If the extension is not installed in this browser, open this page from the
|
If the extension is not installed in this browser, open this page from the browser that
|
||||||
browser that has it installed.
|
has it installed.
|
||||||
</li>
|
</li>
|
||||||
<li data-i18n="tip_refresh">Refresh this page after installing or updating.</li>
|
<li data-i18n="tip_refresh">Refresh this page after installing or updating.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<a href="https://alibaba.github.io/page-agent/docs/introduction/overview" target="_blank" data-i18n="link_docs">Docs</a>
|
<a
|
||||||
<a href="https://github.com/alibaba/page-agent/issues" target="_blank" data-i18n="link_issues">Report an Issue</a>
|
href="https://alibaba.github.io/page-agent/docs/introduction/overview"
|
||||||
|
target="_blank"
|
||||||
|
data-i18n="link_docs"
|
||||||
|
>Docs</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://github.com/alibaba/page-agent/issues"
|
||||||
|
target="_blank"
|
||||||
|
data-i18n="link_issues"
|
||||||
|
>Report an Issue</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -197,8 +210,7 @@
|
|||||||
install_sub: 'Page Agent 需要安装最新版浏览器插件才能运行。',
|
install_sub: 'Page Agent 需要安装最新版浏览器插件才能运行。',
|
||||||
install_btn: '从 Chrome 应用商店安装',
|
install_btn: '从 Chrome 应用商店安装',
|
||||||
tip_outdated: '如果插件版本过旧,请更新到最新版本。',
|
tip_outdated: '如果插件版本过旧,请更新到最新版本。',
|
||||||
tip_other_browser:
|
tip_other_browser: '如果该浏览器中未安装插件,请从装有插件的浏览器打开此页面。',
|
||||||
'如果该浏览器中未安装插件,请从装有插件的浏览器打开此页面。',
|
|
||||||
tip_refresh: '安装或更新后,请刷新此页面。',
|
tip_refresh: '安装或更新后,请刷新此页面。',
|
||||||
link_docs: '文档',
|
link_docs: '文档',
|
||||||
link_issues: '问题反馈',
|
link_issues: '问题反馈',
|
||||||
@@ -220,13 +232,9 @@
|
|||||||
if (!globalThis.chrome?.runtime?.sendMessage) {
|
if (!globalThis.chrome?.runtime?.sendMessage) {
|
||||||
showInstall()
|
showInstall()
|
||||||
} else {
|
} else {
|
||||||
chrome.runtime.sendMessage(
|
chrome.runtime.sendMessage(EXT_ID, { type: 'OPEN_HUB', wsPort }, (response) => {
|
||||||
EXT_ID,
|
|
||||||
{ type: 'OPEN_HUB', wsPort },
|
|
||||||
(response) => {
|
|
||||||
if (chrome.runtime.lastError || !response?.ok) showInstall()
|
if (chrome.runtime.lastError || !response?.ok) showInstall()
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
showInstall()
|
showInstall()
|
||||||
|
|||||||
@@ -49,10 +49,34 @@
|
|||||||
<div id="sk">
|
<div id="sk">
|
||||||
<p class="sk-text" id="sk-text">Loading...</p>
|
<p class="sk-text" id="sk-text">Loading...</p>
|
||||||
<style>
|
<style>
|
||||||
#sk{display:flex;align-items:center;justify-content:center;min-height:100vh;background:linear-gradient(135deg,#eff6ff,#f5f3ff)}
|
#sk {
|
||||||
@media(prefers-color-scheme:dark){#sk{background:linear-gradient(135deg,#111827,#1f2937)}}
|
display: flex;
|
||||||
.sk-text{font:400 14px/1 system-ui,sans-serif;color:#94a3b8;animation:skf 2s ease-in-out infinite}
|
align-items: center;
|
||||||
@keyframes skf{0%,100%{opacity:.6}50%{opacity:.3}}
|
justify-content: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: linear-gradient(135deg, #eff6ff, #f5f3ff);
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
#sk {
|
||||||
|
background: linear-gradient(135deg, #111827, #1f2937);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sk-text {
|
||||||
|
font:
|
||||||
|
400 14px/1 system-ui,
|
||||||
|
sans-serif;
|
||||||
|
color: #94a3b8;
|
||||||
|
animation: skf 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes skf {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
55
scripts/ci.js
Normal file
55
scripts/ci.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* CI check script. Run locally before commit or in GitHub Actions.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/ci.js # run all checks
|
||||||
|
* node scripts/ci.js --no-build # skip build step
|
||||||
|
*/
|
||||||
|
import chalk from 'chalk'
|
||||||
|
import { execSync } from 'child_process'
|
||||||
|
|
||||||
|
import { parallelTask } from './parallel-task.js'
|
||||||
|
|
||||||
|
const args = new Set(process.argv.slice(2))
|
||||||
|
const skipBuild = args.has('--no-build')
|
||||||
|
|
||||||
|
function run(label, command) {
|
||||||
|
console.log(chalk.bgBlue.white.bold(` ▸ ${label} `))
|
||||||
|
execSync(command, { stdio: 'inherit' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMainBranch() {
|
||||||
|
if (process.env.GITHUB_REF) return process.env.GITHUB_REF === 'refs/heads/main'
|
||||||
|
try {
|
||||||
|
return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim() === 'main'
|
||||||
|
} catch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Commitlint — skip on main
|
||||||
|
if (isMainBranch()) {
|
||||||
|
console.log(chalk.dim(' ▸ commitlint (skipped on main)'))
|
||||||
|
} else {
|
||||||
|
const from = execSync('git merge-base origin/main HEAD', { encoding: 'utf-8' }).trim()
|
||||||
|
run('commitlint', `npx commitlint --from ${from} --to HEAD`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Lint + Format + Typecheck in parallel
|
||||||
|
console.log(chalk.bgBlue.white.bold(' ▸ lint + format + typecheck '))
|
||||||
|
await parallelTask(
|
||||||
|
[
|
||||||
|
{ label: 'lint', command: 'npm run lint' },
|
||||||
|
{ label: 'format', command: 'npx prettier --check .' },
|
||||||
|
{ label: 'typecheck', command: 'npm run typecheck' },
|
||||||
|
],
|
||||||
|
{ timeoutMs: 120_000 }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 3. Build
|
||||||
|
if (skipBuild) {
|
||||||
|
console.log(chalk.dim(' ▸ build (skipped)'))
|
||||||
|
} else {
|
||||||
|
run('build', 'npm run build')
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user