diff --git a/.gitea/workflows/devstar-vscode-release.yaml b/.gitea/workflows/devstar-vscode-release.yaml index 9ea29b8..ce4f729 100644 --- a/.gitea/workflows/devstar-vscode-release.yaml +++ b/.gitea/workflows/devstar-vscode-release.yaml @@ -7,17 +7,59 @@ on: branches: - main +permissions: + contents: write + jobs: build: runs-on: ubuntu-latest container: image: node:20-alpine steps: + - name: 安装 Git + run: | + apk add --no-cache git + - name: 拉取代码 - uses: https://devstar.cn/actions/checkout@v4 + uses: actions/checkout@v4 with: + token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 + - name: 配置 Git + run: | + # 添加工作目录为安全目录 + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git config --global --add safe.directory /github/workspace + + # 配置用户信息 + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + + - name: 自动递增版本号 + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + apk add --no-cache jq + CURRENT_VERSION=$(jq -r '.version' package.json) + echo "当前版本: $CURRENT_VERSION" + + # 分解版本号 + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION" + + # 递增补丁版本号 + NEW_PATCH=$((PATCH + 1)) + NEW_VERSION="$MAJOR.$MINOR.$NEW_PATCH" + echo "新版本: $NEW_VERSION" + + # 更新 package.json + jq --arg version "$NEW_VERSION" '.version = $version' package.json > package.json.tmp + mv package.json.tmp package.json + + # 提交版本变更 + git add package.json + git commit -m "chore: bump version to $NEW_VERSION [skip ci]" + git push + - name: 安装依赖 run: | npm install @@ -27,7 +69,7 @@ jobs: npm run package - name: 发布插件 - if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main' + if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: | npm run publish env: diff --git a/package.json b/package.json index 6a09a0c..865a752 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "devstar", "displayName": "%displayName%", "description": "%description%", - "version": "0.4.1", + "version": "0.4.3", "keywords": [], "publisher": "mengning", "engines": { diff --git a/src/home.ts b/src/home.ts index 4132ade..08c27e7 100644 --- a/src/home.ts +++ b/src/home.ts @@ -79,7 +79,33 @@ export default class DSHome { async (message) => { const data = message.data; const need_return = message.need_return; - if (!need_return) { + + if (need_return) { + // 处理需要返回结果的消息 + switch (message.command) { + case 'getUserToken': + panel.webview.postMessage({ + command: 'getUserToken', + data: { userToken: this.user.getUserTokenFromLocal() } + }); + break; + + case 'getUsername': + panel.webview.postMessage({ + command: 'getUsername', + data: { username: this.user.getUsernameFromLocal() } + }); + break; + + case 'getDevstarDomain': + panel.webview.postMessage({ + command: 'getDevstarDomain', + data: { devstarDomain: this.devstarDomain } + }); + break; + } + } else { + // 处理不需要返回结果的消息 switch (message.command) { case 'openExternalUrl': const url = message.url || (data && data.url); @@ -96,6 +122,18 @@ export default class DSHome { vscode.window.showErrorMessage('打开链接失败: 链接地址无效'); } break; + + case 'showInformationNotification': + if (data && data.message) { + vscode.window.showInformationMessage(data.message); + } + break; + + case 'showErrorNotification': + if (data && data.message) { + vscode.window.showErrorMessage(data.message); + } + break; } } }, diff --git a/src/main.ts b/src/main.ts index 00373ca..4d0c822 100644 --- a/src/main.ts +++ b/src/main.ts @@ -66,31 +66,17 @@ export class DevStarExtension { const path = params.get('path'); const accessToken = params.get('access_token'); const devstarUsername = params.get('devstar_username'); - const rawDevstarDomain = params.get('devstar_domain'); - let devstarDomain = rawDevstarDomain; - if (rawDevstarDomain) { - try { - const url = new URL(rawDevstarDomain); - devstarDomain = `${url.protocol}//${url.hostname}`; + const devstarDomain = params.get('devstar_domain'); + const forwardPortsParam = params.get('forwardPorts'); - // 从 rawDevstarDomain 的查询参数中提取 forwardPorts - const forwardPortsParam = url.searchParams.get('forwardPorts'); - if (forwardPortsParam) { - const ports = forwardPortsParam.split(',').map(port => parseInt(port, 10)).filter(port => !isNaN(port)); - console.log('解析到的 forwardPorts 参数:', ports); - context.globalState.update('forwardPorts', ports); - } else { - // 如果没有 forwardPorts 参数,清除 globalState 中的旧值 - console.log('未找到 forwardPorts 参数,清除旧的 forwardPorts 配置'); - context.globalState.update('forwardPorts', undefined); - } - } catch (error) { - console.error('Invalid devstar_domain URL:', error); - } + // 处理 forwardPorts 参数 + if (forwardPortsParam) { + const ports = forwardPortsParam.split(',').map(port => parseInt(port, 10)).filter(port => !isNaN(port)); + context.globalState.update('forwardPorts', ports); + } else { + // 如果没有 forwardPorts 参数,清除 globalState 中的旧值 + context.globalState.update('forwardPorts', undefined); } - console.log('sanitized_devstar_domain:', devstarDomain); - - // 使用修正后的 devstar_domain if (devstarDomain) { this.user.setDevstarDomain(devstarDomain); this.remoteContainer.setUser(this.user); diff --git a/src/remote-container.ts b/src/remote-container.ts index 290f4b5..1357edf 100644 --- a/src/remote-container.ts +++ b/src/remote-container.ts @@ -263,24 +263,32 @@ export default class RemoteContainer { `root@${hostname}` ]; - const sshProcess = spawn('ssh', sshArgs); + // 使用 detached 选项让 SSH 进程独立运行,不随父进程退出 + const sshProcess = spawn('ssh', sshArgs, { + detached: true, // 让进程在后台独立运行 + stdio: 'ignore' // 忽略输入输出,避免进程挂起 + }); + + // 解除父进程对子进程的引用,使其真正独立 + sshProcess.unref(); sshProcess.on('error', (error: Error) => { reject(error); }); - sshProcess.stdout.on('data', (_data: Buffer) => { - }); + // 由于使用了 stdio: 'ignore',这些事件监听器不再需要 + // sshProcess.stdout.on('data', (data: Buffer) => { + // console.log(`[SSH stdout] ${data.toString()}`); + // }); - sshProcess.stderr.on('data', (_data: Buffer) => { - }); + // sshProcess.stderr.on('data', (data: Buffer) => { + // console.error(`[SSH stderr] ${data.toString()}`); + // }); - if (!this.sshProcesses) { - this.sshProcesses = new Map(); - } - const key = `${hostname}:${sshPort}:${containerPort}`; - this.sshProcesses.set(key, sshProcess); + // 注意:由于进程已 detached 和 unref,不再需要保存到 sshProcesses Map + // 因为我们无法也不需要控制这些独立进程的生命周期 + // 等待 SSH 连接建立 setTimeout(() => { resolve(); }, 2000); @@ -355,6 +363,7 @@ export default class RemoteContainer { async openRemoteFolder(host: string, port: number, _username: string, path: string, context: vscode.ExtensionContext): Promise { try { const sshConfig = await this.getSSHConfig(host); + if (sshConfig) { try { // 调用 setupPortForwardingFromGlobalState 方法