From bb66d89c642afc0db5360dcdd314d8d74c4baeee Mon Sep 17 00:00:00 2001 From: Yao Jingxi <23722032@bjtu.edu.cn> Date: Thu, 5 Nov 2026 13:37:58 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20Java=20=E6=8F=92=E4=BB=B6=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=99=AE=E9=80=9A=E6=8F=92=E4=BB=B6=E8=BA=AB=E4=BB=BD?= =?UTF-8?q?=EF=BC=8C=E5=8E=BB=E6=8E=89=E5=8F=91=E5=B8=83=E8=80=85=E7=AD=BE?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lithe 不再区分官方插件和普通插件。Java 插件和 Cargo、Maven、Gradle 一样 使用 io.github.lithe-idea.* 身份,不带发布者签名,由 Lithe Store 自动收录。 - 插件 ID 从 dev.lithe.plugin.java-support 改为 io.github.lithe-idea.java-support, 包目录随之改名;vendor 改为 Lithe Community(signatureRequirement: none), 删除 bundledSignatureRequirement 和 requires.packageTrust - 删除签名链路:scripts/host-tools.sh、host-tools.lock.json、构建和归档里的 签名器与官方校验器调用;CI 和发布不再需要 Xcode 和签名密钥 - build-package.sh 只接受 --arch,组装后直接校验;archive-package.sh 输出 dist/Lithe-Java-Support-<版本>-darwin-.zip 和 .sha256,解包后再校验 - verify-package.sh 要求 vendor.signatureRequirement 为 none、包内没有签名文件, 保留 JDK 上游 Apple 代码签名检查 - CI 的打包任务在 Draft PR 上跳过;发布仍为预发布,发布说明改为中文 - 测试里的插件 ID 改为 io.github.lithe-idea.*;repository_pins 断言新身份 - README、MIGRATION、NOTICE 同步新身份、收录方式和转正式发布前的两条宿主限制 --- .github/workflows/ci.yml | 20 +-- .github/workflows/release.yml | 47 +++---- MIGRATION.md | 96 ++++++++++--- NOTICE | 4 +- README.md | 68 +++++---- backend/src/plugin_functions.rs | 132 +++++++++++------- backend/tests/repository_pins.rs | 22 ++- .../src/lsp/languages/jdt_contributions.rs | 20 +-- host-tools.lock.json | 6 - .../icons/LICENSE-APACHE-2.0.txt | 0 .../icons/NOTICE.txt | 0 .../icons/java.svg | 0 .../icons/java_dark.svg | 0 .../icons/maven.svg | 0 .../icons/maven_dark.svg | 0 .../icons/spring-boot.svg | 0 .../icons/spring-boot_dark.svg | 0 .../plugin.json | 11 +- .../templates/java/gradle-groovy/build.gradle | 0 .../java/gradle-groovy/dot-gitignore | 0 .../java/gradle-groovy/settings.gradle | 0 .../java/gradle-kotlin/build.gradle.kts | 0 .../java/gradle-kotlin/dot-gitignore | 0 .../java/gradle-kotlin/settings.gradle.kts | 0 .../templates/java/maven/dot-gitignore | 0 .../templates/java/maven/pom.xml | 0 .../java/plain-empty/src/dot-gitkeep | 0 .../templates/java/plain-sample/src/Main.java | 0 .../templates/java/plain/dot-gitignore | 0 .../standard-empty/src/main/java/dot-gitkeep | 0 .../src/main/resources/dot-gitkeep | 0 .../standard-empty/src/test/java/dot-gitkeep | 0 .../java/standard-sample-main/Main.java | 0 .../src/main/resources/dot-gitkeep | 0 .../standard-sample/src/test/java/dot-gitkeep | 0 scripts/archive-package.sh | 58 ++------ scripts/assemble-package.sh | 4 +- scripts/build-package.sh | 20 ++- scripts/host-tools.sh | 83 ----------- scripts/verify-package.sh | 33 ++--- 40 files changed, 280 insertions(+), 344 deletions(-) delete mode 100644 host-tools.lock.json rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/LICENSE-APACHE-2.0.txt (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/NOTICE.txt (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/java.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/java_dark.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/maven.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/maven_dark.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/spring-boot.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/icons/spring-boot_dark.svg (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/plugin.json (98%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-groovy/build.gradle (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-groovy/dot-gitignore (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-groovy/settings.gradle (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-kotlin/build.gradle.kts (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-kotlin/dot-gitignore (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/gradle-kotlin/settings.gradle.kts (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/maven/dot-gitignore (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/maven/pom.xml (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/plain-empty/src/dot-gitkeep (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/plain-sample/src/Main.java (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/plain/dot-gitignore (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-empty/src/main/java/dot-gitkeep (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-empty/src/main/resources/dot-gitkeep (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-empty/src/test/java/dot-gitkeep (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-sample-main/Main.java (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-sample/src/main/resources/dot-gitkeep (100%) rename {dev.lithe.plugin.java-support => io.github.lithe-idea.java-support}/templates/java/standard-sample/src/test/java/dot-gitkeep (100%) delete mode 100755 scripts/host-tools.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 905249e..aceeec8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,12 +46,6 @@ jobs: - uses: actions/checkout@v4 with: persist-credentials: false - # The host tools build with the Swift compiler of the pinned Lithe - # revision; scripts/host-tools.sh --require-pinned-swift checks it. - - name: Select Xcode 26.6 - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: "26.6" # Downloads are named by their SHA-256 and verified again before use. - name: Restore verified third-party downloads uses: actions/cache@v4 @@ -60,23 +54,17 @@ jobs: .artifacts/jdtls-downloads .artifacts/jdk-downloads key: third-party-${{ hashFiles('third_party/*/manifest.json') }} - - name: Build the Lithe package tools - id: host-tools - run: echo "bin=$(scripts/host-tools.sh --require-pinned-swift)" >> "$GITHUB_OUTPUT" - name: Build, verify and archive both architectures - env: - HOST_TOOLS: ${{ steps.host-tools.outputs.bin }} run: | set -euo pipefail for arch in arm64 x86_64; do - package=$(scripts/build-package.sh --arch "$arch" --host-tools "$HOST_TOOLS") - scripts/archive-package.sh --package "$package" --arch "$arch" \ - --development-unsigned --host-tools "$HOST_TOOLS" + package=$(scripts/build-package.sh --arch "$arch") + scripts/archive-package.sh --package "$package" --arch "$arch" done - - name: Upload the unsigned development archives + - name: Upload the archives uses: actions/upload-artifact@v4 with: - name: java-support-unsigned + name: java-support-archives path: dist/ retention-days: 7 if-no-files-found: error diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8269d42..0ccdf8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,15 +1,21 @@ name: Release # Push a tag v matching plugin.json to publish a GitHub Release with -# one publisher-signed archive per macOS architecture and its SHA-256 file. +# one unsigned plugin archive per macOS architecture and its SHA-256 file. # -# Only the "Sign, archive and publish" step receives the signing key; the -# steps before it build and verify unsigned packages. Checkouts do not keep -# the workflow token. +# No step receives a signing key. Checkouts do not keep the workflow token. # -# Releases are published as pre-releases: Lithe still bundles Java Support and -# lists it from its own official index (see MIGRATION.md). Remove --prerelease -# below once the official index lists this repository's releases. +# Releases stay pre-releases, which Lithe Store's tracker skips, for two +# reasons: +# 1. Lithe still bundles Java Support under the old ID +# dev.lithe.plugin.java-support. +# 2. Current Lithe hosts reserve languageServers[].hostIntegration (the JDT +# integration) to dev.lithe.* plugin IDs and accept the short tool ID +# "java" only from verified official provenance, so they reject this +# package. +# Remove --prerelease below once a stable Lithe accepts the package (stage E in +# MIGRATION.md) and stops bundling Java Support. The Store then lists stable +# releases of this repository automatically. on: push: tags: ["v*"] @@ -56,41 +62,34 @@ jobs: - name: Check the tag matches plugin.json run: | set -euo pipefail - version=$(plutil -extract version raw -o - dev.lithe.plugin.java-support/plugin.json) + version=$(plutil -extract version raw -o - io.github.lithe-idea.java-support/plugin.json) if [[ "$GITHUB_REF_NAME" != "v$version" ]]; then echo "::error::Tag $GITHUB_REF_NAME does not match plugin.json version $version" exit 1 fi - - name: Select Xcode 26.6 - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: "26.6" - - name: Build the Lithe package tools - id: host-tools - run: echo "bin=$(scripts/host-tools.sh --require-pinned-swift)" >> "$GITHUB_OUTPUT" - name: Build and verify both architectures - env: - HOST_TOOLS: ${{ steps.host-tools.outputs.bin }} run: | set -euo pipefail for arch in arm64 x86_64; do - scripts/build-package.sh --arch "$arch" --host-tools "$HOST_TOOLS" + scripts/build-package.sh --arch "$arch" done - - name: Sign, archive and publish + - name: Archive and publish env: - HOST_TOOLS: ${{ steps.host-tools.outputs.bin }} - LITHE_PLUGIN_PACKAGE_PRIVATE_KEY: ${{ secrets.LITHE_PLUGIN_PACKAGE_PRIVATE_KEY }} GH_TOKEN: ${{ github.token }} run: | set -euo pipefail checksums="$RUNNER_TEMP/checksums.txt" : > "$checksums" for arch in arm64 x86_64; do - scripts/archive-package.sh --package ".artifacts/package/$arch/dev.lithe.plugin.java-support" \ - --arch "$arch" --sign --host-tools "$HOST_TOOLS" >> "$checksums" + scripts/archive-package.sh --package ".artifacts/package/$arch/io.github.lithe-idea.java-support" \ + --arch "$arch" >> "$checksums" done { - echo "Lithe 官方 Java 插件 dev.lithe.plugin.java-support ${GITHUB_REF_NAME#v}。每个 macOS 架构一个经发布者签名的归档,附 SHA-256 文件。" + echo "Java Support(\`io.github.lithe-idea.java-support\`)${GITHUB_REF_NAME#v}。每个 macOS 架构一个归档,附 SHA-256 文件。" + echo + echo "兼容性:目前的 Lithe 仍内置 Java Support,并且只允许 \`dev.lithe.*\` 插件使用 JDT 宿主集成和短工具 ID \`java\`,所以会拒绝安装这个包;要等 Lithe 主仓库完成 Java 拆分的阶段 E。" + echo + echo "安装:预发布版本,Lithe Store 自动追踪会跳过。宿主支持后下载对应架构的 ZIP,在 设置 → 插件 的 ⚙ 菜单中选择 从磁盘安装插件…。" echo echo "SHA-256:" echo '```' diff --git a/MIGRATION.md b/MIGRATION.md index 8761c75..6107691 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,6 +1,6 @@ # 迁移说明:Java 逻辑从 Lithe 主仓库移到本仓库 -本文是 Java Support 插件(`dev.lithe.plugin.java-support`)从 Lithe 主仓库拆分出来的移植账本,回答四个问题: +本文是 Java Support 插件(`io.github.lithe-idea.java-support`)从 Lithe 主仓库拆分出来的移植账本,回答四个问题: 1. 主仓库里的每个 Java 相关文件或符号,现在在本仓库的哪里,状态是什么。 2. 哪些部分在等宿主(Lithe Core 与 macOS 应用)提供通用插件 API,等的是计划里的哪个编号。 @@ -23,7 +23,7 @@ 还没有运行过,见第 10 节。 - 18 个 fixture(共 1,234 行)放在 `fixtures/`。其中 12 个被 Rust 测试读取;另外 6 个是从主仓库复制来的契约样例, 暂时没有 Rust 测试读取(见第 7 节)。 - - 插件包:`dev.lithe.plugin.java-support/`,加上组装、校验、归档脚本、CI 和发布工作流。 + - 插件包:`io.github.lithe-idea.java-support/`,加上组装、校验、归档脚本、CI 和发布工作流。 - 领域代码的注释(`//!`、`///`)全部是英文。每个来自 Core 或 Swift 的模块在模块文档里写明来源。 - 宿主侧还没有接线:`plugin.json` 暂时不声明 `backend`(`backend/tests/repository_pins.rs` 里有测试断言这一点), 后端目前只把领域命令注册成插件函数,并带着跨插件函数的调用方一侧(第 5 节),等第 6 节列出的宿主 API 就位后再声明。 @@ -191,7 +191,7 @@ API-30(调试适配器)、API-37(环境与 l10n)、API-42(内置 Git | `…/Models/AppModel/AppModel+JavaLaunchDecision.swift@1daaeb525`、`AppModel+JavaLaunchPreparation.swift@1daaeb525`、`Views/Run/JavaLaunchDecisionDialog.swift@1daaeb525`、`Views/Run/JavaRunConfigurationEditorView.swift@1daaeb525` | 无;规则在 `java_launch.rs`、`java_selection.rs` | 等待宿主 API(API-29) | 运行配置编辑与启动决策由宿主通用界面承载,Java 字段由插件声明 | | `…/Models/AppModel/AppModel+JavaIndex.swift@1daaeb525`、`Application/Features/SpringFeatureModel.swift@1daaeb525`、`MybatisFeatureModel.swift@1daaeb525`、`Core/Rust/RustJavaMavenOperations.swift@1daaeb525` | 无;索引规则在 `spring.rs`、`mybatis.rs` | 等待宿主 API(API-25) | 补全、悬浮、诊断、导航由插件作为语言提供者给出 | | `…/Views/Run/SpringEndpointsView.swift@1daaeb525` | 无 | 等待宿主 API(API-27) | Endpoints 面板需要插件原生界面的承载方式;本文不新增编号,落点待协调者确认 | -| `…/Theme/JavaFileIconResolver.swift@1daaeb525` | 图标在 `dev.lithe.plugin.java-support/icons/` | 等待宿主 API(API-27) | 文件图标由插件贡献 | +| `…/Theme/JavaFileIconResolver.swift@1daaeb525` | 图标在 `io.github.lithe-idea.java-support/icons/` | 等待宿主 API(API-27) | 文件图标由插件贡献 | | `…/Application/Features/JavaPluginTransition.swift@1daaeb525`、`AppModel+JavaPlugin.swift@1daaeb525` | 无 | 不移植(宿主"推荐安装 Java Support"的引导,应由商店索引取代,不是插件逻辑) | | | `…/Views/Language/JavaProblemsView.swift@1daaeb525`、`JavaReferencesView.swift@1daaeb525` | 无 | 不移植(宿主通用的问题和引用视图,没有 Java 领域规则,只需改名) | | | `…/Models/Java/{JavaDiagnosticModels,JavaNavigationModels,MybatisModels,SpringModels,ActiveTestTarget}.swift@1daaeb525` | 无;JSON 形状在 `dj/protocol/contracts.rs` | 不移植(宿主界面模型) | | @@ -219,17 +219,17 @@ API-30(调试适配器)、API-37(环境与 l10n)、API-42(内置 Git | 来源 | 新位置 | 状态 | 说明 | | --- | --- | --- | --- | -| `Plugins/mac/Official/JavaSupport/plugin.json@1daaeb525` | `dev.lithe.plugin.java-support/plugin.json` | 已移植并有测试 | 身份、`requires`、权限、设置不变;`backend` 暂不声明,测试断言这一点 | -| `Plugins/mac/Official/JavaSupport/{icons,templates}/**@1daaeb525` | `dev.lithe.plugin.java-support/{icons,templates}/` | 已移植并有测试 | `backend/tests/repository_pins.rs` 检查清单里每个文件都存在;Maven 图标和模板的归属见第 7 节 | +| `Plugins/mac/Official/JavaSupport/plugin.json@1daaeb525` | `io.github.lithe-idea.java-support/plugin.json` | 已移植并有测试 | 身份改为普通插件:id 从 `dev.lithe.plugin.java-support` 变为 `io.github.lithe-idea.java-support`,`vendor` 改为 `Lithe Community`(`signatureRequirement: none`),删除 `publisherPackage`、`bundledSignatureRequirement` 和 `requires.packageTrust`,见第 9 节;版本仍是 1.1.0,权限、设置和其余 `requires` 不变;`backend` 暂不声明。`repository_pins.rs` 的 `the_manifest_keeps_the_community_identity_and_declares_no_backend_yet` 断言这两点 | +| `Plugins/mac/Official/JavaSupport/{icons,templates}/**@1daaeb525` | `io.github.lithe-idea.java-support/{icons,templates}/` | 已移植并有测试 | `backend/tests/repository_pins.rs` 检查清单里每个文件都存在;Maven 图标和模板的归属见第 7 节 | | `Plugins/mac/Official/JavaSupport/assemble-package.sh@1daaeb525` | `scripts/assemble-package.sh` | 已移植无测试 | 由 `scripts/verify-package.sh` 校验产物 | | `scripts/macos/prepare/prepare-jdtls.sh@1daaeb525`、`prepare-jdk.sh@1daaeb525` | `scripts/prepare-jdtls.sh`、`scripts/prepare-jdk.sh` | 已移植无测试 | 来源地址和 SHA-256 固定在 `third_party/*/manifest.json`,`repository_pins.rs` 检查格式 | | `third_party/jdtls/manifest.json@1daaeb525`、`third_party/jdk/manifest.json@1daaeb525` | `third_party/jdtls/manifest.json`、`third_party/jdk/manifest.json` | 已移植并有测试 | 每个地址是 HTTPS,每个校验和是小写 SHA-256 | -| `.github/workflows/ci-plugins.yml@1daaeb525`、`release-official-plugins.yml@1daaeb525` 里 Java 的部分 | `.github/workflows/ci.yml`、`release.yml` | 已移植无测试 | 发布流程只有签名步骤拿私钥,见第 9 节 | -| `scripts/plugins/{build,verify}-official-plugins.sh@1daaeb525` 里 Java 的部分 | `scripts/build-package.sh`、`archive-package.sh`、`verify-package.sh`、`host-tools.sh` | 已移植无测试 | 宿主工具(签名器、校验器)按固定提交构建,见第 9 节 | +| `.github/workflows/ci-plugins.yml@1daaeb525`、`release-official-plugins.yml@1daaeb525` 里 Java 的部分 | `.github/workflows/ci.yml`、`release.yml` | 已移植无测试 | 发布流程没有签名步骤,不读任何密钥,见第 9 节 | +| `scripts/plugins/{build,verify}-official-plugins.sh@1daaeb525` 里 Java 的部分 | `scripts/build-package.sh`、`archive-package.sh`、`verify-package.sh` | 已移植无测试 | 主仓库脚本里构建并调用签名器(`LithePluginPackageSigner`)和官方校验器(`LitheOfficialPluginVerifier`)的部分不移植:普通插件包不带发布者签名,所以不需要它们,也不需要 Swift 工具链;`verify-package.sh` 改为要求 `vendor.signatureRequirement` 为 `none` 且包里没有 `lithe-plugin-signature.json`,见第 9 节 | | `scripts/windows/prepare/prepare-jdtls.ps1@1daaeb525`、`prepare-jdk.ps1@1daaeb525` | 无 | 不移植(Windows 插件包不在本阶段;Windows 仍在用) | `third_party/jdk/manifest.json` 保留了 Windows 条目,供以后使用 | | `scripts/resources/worktree-resources.json@1daaeb525` 里 Java 的条目 | 无 | 不移植(主仓库的工作树复用清单,随主仓库删除同步更新) | 见第 8 节 | | `scripts/architecture/verify-java-semantic-ownership.mjs@1daaeb525` | 无 | 不移植(由主仓库新的"宿主不含语言专属内容"闸门取代) | | -| `Plugins/marketplace/official-plugins.json@1daaeb525` 的 Java 条目 | 无 | 不移植(商店索引在主仓库,发布稳定版后才改) | 第 9 节 | +| `Plugins/marketplace/official-plugins.json@1daaeb525` 的 Java 条目 | 无 | 不移植(普通插件由 Lithe Store 收录,不进主仓库的索引;主仓库内置的官方条目在阶段 E 退役) | 第 8.2 节、第 9 节 | ### 3.6 Windows 与共享前端、功能矩阵、文案 @@ -457,11 +457,19 @@ Java 后端向宿主查询导出测试运行函数 ID 的已启用插件,把 - Core 的跨插件函数中转(API-35)合并,Maven/Gradle 插件导出 `languageImport.settings`。 - 宿主的语言服务器通道(API-25)、编辑器标记(API-27)、运行与测试(API-29)合并,Java 插件声明 `backend` 并通过 e2e。 -- 本仓库发布一个签名的、支持 API 4 的版本;只有当稳定版 Lithe 支持这个 API 版本时才能转正(见第 9 节)。 +- 本仓库发布一个支持 API 4 的预发布版本(普通插件,不带发布者签名);转为正式发布要等第 8.2 节列出的两条宿主限制取消、 + 主仓库不再内置 Java Support(见第 9 节)。 -### 8.2 macOS 阶段:Core 与 macOS 应用 +### 8.2 macOS 阶段(阶段 E):Core 与 macOS 应用 + +本仓库的 README、发布工作流和 Release 说明里说的"主仓库阶段 E",指的就是这一节的删除。 - Core: + - 取消两条按官方身份设的宿主限制,本插件才能作为普通插件被宿主接受: + - `rust/lithe-core/src/plugins/declarative.rs` 把 `languageServers[].hostIntegration`(JDT)限定给 `dev.lithe.*` 插件 ID, + 其他 ID 得到错误 `plugin.integration.unsupported`。这个限制随 JDT 宿主集成一起,由通用 API 取代后消失。 + - `rust/lithe-core/src/toolchain/definitions.rs` 只对带宿主验证过的官方来源的包接受 `java` 这样的短 `toolDefinitions` ID。 + 要改成对 `java` 工具 ID 使用一条不依赖官方身份的规则(Maven 插件依赖工具 ID `java`)。 - `lsp/languages/{java_*,jdt*,project_preparation}.rs` 与 `mod.rs` 里的 re-export,`languages/{java,java_syntax,spring,mybatis}.rs`, `debug/java_test.rs`,`execution/{java_selection,launch_command,classpath_jar}.rs` 的 Java 部分,`protocol/contracts.rs` 里的 Java、Spring、MyBatis、Maven 模型。 - `protocol/command.rs` 与 `runtime/dispatcher.rs` 里的 Java 命令;`engine.rs` 里的 Java 函数与 `StartServerRequest` 的 Java 字段; @@ -476,6 +484,10 @@ Java 后端向宿主查询导出测试运行函数 ID 的已启用插件,把 `BuiltInModuleCatalog` 里的 Java 条目。 - 宿主资源与脚本: - `Plugins/mac/Official/JavaSupport` 迁出后删除;`scripts/macos/prepare/prepare-{jdtls,jdk}.sh`(Windows 的 `.ps1` 不动)。 + - 不再内置 Java Support:退役内置的官方条目 `dev.lithe.plugin.java-support`(`Plugins/marketplace/official-plugins.json` 里 + `releaseEnabled: false`、`bundledUntilPublishedVersion: "1.1.0"` 的那一条),并把用户迁移到新 ID `io.github.lithe-idea.java-support`。 + 先例是 Go 和 PHP 在主仓库 [#1357](https://github.com/1lck/Lithe-IDEA/pull/1357) 改成社区插件:旧 ID 留在 `OfficialPluginCatalog`, + 用 `communityReplacementID` 指向替代者。本插件发布稳定版之后,由 Lithe Store 自动上架,不在主仓库的索引里加条目。 - `scripts/resources/worktree-resources.json` 里 `jdtls`、`jdk`、`jdt-maven-settings`、`java-launch-temporaries`、Java 插件包路径的条目, 以及复用脚本的校验路由、对应测试和 `docs/ci-builds.md` 的"独立工作树的本地编译"章节,要在同一个 PR 里同步更新(AGENTS.md 的规定)。 - `scripts/architecture/verify-java-semantic-ownership.mjs` 由新的闸门取代;`ci-plugins.yml` 里的 `jdtls: "true"`,`release-official-plugins.yml` 里的路径。 @@ -490,28 +502,66 @@ Java 后端向宿主查询导出测试运行函数 ID 的已启用插件,把 `scripts/windows/prepare/prepare-{jdtls,jdk}.ps1`、`tauri.jdtls.conf.json`。 - 这些在 Windows 宿主能安装并运行本插件之前,不能删。 -## 9. 发布、签名与商店 +## 9. 发布与商店 + +### 9.1 身份与收录策略 + +- Lithe 不再区分官方插件和普通插件,所有插件都按普通插件处理,不带发布者签名。区别只在 [Lithe Store](https://github.com/Lithe-IDEA/Lithe-store) + 怎样收录:Lithe-IDEA 组织里 `lithe-plugin-*` 仓库的稳定版(非预发布)GitHub Release 由商店机器人自动跟踪并上架; + 组织之外的插件向 Lithe-store 提交 pull request,维护者审核后上架。 +- 本插件的 id 是 `io.github.lithe-idea.java-support`,`vendor` 是 + `{ "id": "io.github.lithe-idea", "displayName": "Lithe Community", "signatureRequirement": "none" }`。 + 它在主仓库里原来是 `dev.lithe.plugin.java-support`,`vendor` 为 `dev.lithe`,带 `publisherPackage` 和 `bundledSignatureRequirement: sameTeamAsHost`; + 这两项随官方身份一起删除。`requires.packageTrust` 也删除,因为它只服务 `vendor.bundledSignatureRequirement`。 + 权限、设置和其余 `requires` 不变。版本仍是 1.1.0,新 ID 下还没有发布过任何版本。 +- `backend/tests/repository_pins.rs` 的 `the_manifest_keeps_the_community_identity_and_declares_no_backend_yet` 断言这个身份 + (`vendor`、没有 `bundledSignatureRequirement` 和 `packageTrust`)以及清单里没有 `backend`; + `scripts/verify-package.sh` 要求 `vendor.signatureRequirement` 为 `none`,并拒绝包里的 `lithe-plugin-signature.json`。 + 两者共同保证插件包既不携带发布者签名,也不要求宿主去验证发布者签名。 +- 主仓库里的签名器(`LithePluginPackageSigner`)和官方校验器(`LitheOfficialPluginVerifier`)没有移植,本仓库不构建也不使用它们, + 打包不再需要 Xcode 或 Swift。 + +### 9.2 发布流程 - 标签是 `v`,必须等于 `plugin.json` 的 `version`(当前 1.1.0)。发布资产是 `Lithe-Java-Support-{version}-darwin-{arm64,x64}.zip` - 加 `.sha256`,用 `ditto --keepParent` 制作。 -- 发布工作流分成测试和发布两段,只有最后的签名步骤拿 `LITHE_PLUGIN_PACKAGE_PRIVATE_KEY`;发布标为预发布(`--prerelease`), - 原因是主仓库仍然内置 Java Support(`official-plugins.json` 里 Java 条目 `releaseEnabled: false`,`bundledUntilPublishedVersion: "1.1.0"`), - 而且 `pluginAPIVersion` 4 还没有随稳定版 Lithe 发布。 -- 宿主工具(`LithePluginPackageSigner`、`LitheOfficialPluginVerifier`)从 Lithe 提交 `1daaeb525831999ad518b4c6fd3b11b5b1b64b5a` 构建, - 需要那个提交 `.swift-version` 里的 Swift 6.3.3;固定在 `host-tools.lock.json`。SDK 固定在 `sdk.lock.json` - (`lithe_plugin_sdk` 0.1.0,标签 `sdk-rust-v0.1.0`,提交 `e689971c000c15a044df0502052e7b2c1c6f84f`), + 加 `.sha256`,由 `scripts/archive-package.sh` 用 `ditto --keepParent` 制作;本地开发、CI 和发布用的是同一个脚本、同一种归档。 +- `Release` 工作流先在 Ubuntu 上跑 Rust 检查,再在 macOS 上构建、校验并归档 arm64 与 x86_64 两个包,最后发布。没有任何步骤读取签名密钥。 +- CI 的 `package` 任务(macOS,草稿 PR 不跑)构建并归档同样的两个架构,把 `dist/` 作为 `java-support-archives` 上传。 +- SDK 固定在 `sdk.lock.json`(`lithe_plugin_sdk` 0.1.0,标签 `sdk-rust-v0.1.0`,提交 `e689971c000c15a044df0502052e7b2c1c6f84f`), `scripts/verify-sdk-lock.sh` 检查 `Cargo.lock` 解析到的是同一个提交。 -- 插件包在运行时只读:JDT LS、Lombok、java-debug、vscode-java-test 运行器和 JDK 都在构建阶段固定来源、校验哈希后放进包再签名; - 运行时的状态只写宿主给的状态目录(`--state ${stateDir}`),不写包目录,保证 Sparkle 增量更新的基线不变。 -- 还没有登记到商店索引。登记要等稳定版 Lithe 支持这个 API 版本,并在主仓库的索引里加条目。 + +### 9.3 为什么仍是预发布 + +发布保持为预发布(`--prerelease`),商店的跟踪器会跳过预发布,所以目前不会上架。原因有两个: + +1. 主仓库仍然以旧 ID `dev.lithe.plugin.java-support` 内置 Java Support(`Plugins/marketplace/official-plugins.json` 里的条目 + `releaseEnabled: false`,`bundledUntilPublishedVersion: "1.1.0"`)。 +2. 当前的宿主会拒绝这个包: + - Lithe Core 把 `languageServers[].hostIntegration`(JDT)保留给 `dev.lithe.*` 插件 ID(`rust/lithe-core/src/plugins/declarative.rs`, + 错误 `plugin.integration.unsupported`); + - 短 `toolDefinitions` ID(例如 `java`)只在宿主验证过官方来源时才接受(`rust/lithe-core/src/toolchain/definitions.rs`)。 + 本包两者都用到了。 + +转为正式发布的条件:主仓库完成阶段 E(第 8.2 节),用通用 API 取代 JDT 宿主集成,给 `java` 工具 ID 一条不依赖官方身份的规则 +(Maven 插件依赖工具 ID `java`),并且不再内置 Java Support。之后在 `release.yml` 里去掉 `--prerelease`,商店自动上架稳定版。 +下载的 ZIP 通过 设置 → 插件 的 ⚙ 菜单 → 从磁盘安装插件… 安装,但在此之前当前宿主会按上面的原因拒绝它。 +阶段 E 还要退役内置的 `dev.lithe.plugin.java-support` 条目并把用户迁移到新 ID,见第 8.2 节。 + +### 9.4 运行时只读 + +插件包在运行时只读:JDT LS、Lombok、java-debug、vscode-java-test 运行器和 JDK 都在构建阶段固定来源、校验哈希后放进包里; +运行时的状态只写宿主给的状态目录(`--state ${stateDir}`),不写包目录,保证 Sparkle 增量更新的基线不变。 +包里的 JDK 保留上游的 Apple 代码签名(macOS 只在有这个签名时才会启动它),`scripts/verify-package.sh` 检查这一点; +这是 JDK 自己的签名,不是插件发布者的签名。 ## 10. 未完成事项 - 宿主没有接线:`plugin.json` 没有 `backend` 声明,第 6 节的 API 全部没有实现,三个会话命令只回答 `NotSupported`。 - API-35 的 Java 一侧大部分已实现(第 5 节),但中转协议是暂定的;变化通知函数没有注册;没有任何地方调用 `collect_for_call`(要等 API-25 的启动解析器)。Maven profiles 的逐工程交付形状没有定。 - `jdt_contributions.rs` 和 `plugin_functions.rs` 的 24 个测试只验证了插件内部逻辑:它们已经编译并通过,但用来对照的中转协议是暂定的,等 [#1742](https://github.com/1lck/Lithe-IDEA/pull/1742) 合入后要按最终协议复核。 -- 没有真实 JDT 的端到端测试,也没有在 Linux 上实跑过(本机没有 Docker),没有真实签名。 -- 打包的 `package` 任务只在 macOS 上构建未签名的开发归档,没有在 CI 上跑过一次完整的签名发布。 +- 没有真实 JDT 的端到端测试,也没有在 Linux 上实跑过(本机没有 Docker)。 +- CI 的 `package` 任务构建的归档和正式发布的是同一种(同一组脚本、同一个文件名规则),但还没有真正跑过一次发布工作流: + 新 ID 下没有发布过任何版本,标签触发、预发布 Release 的创建和资产上传都没有被实际验证过。 - Windows 插件包没有做;`third_party/jdk/manifest.json` 里保留了 Windows 条目。 - 6 个 fixture 没有测试读取(第 7 节)。 - Spring Endpoints 面板的插件承载方式没有落点(第 3.3 节)。 diff --git a/NOTICE b/NOTICE index b503a55..49e5f2f 100644 --- a/NOTICE +++ b/NOTICE @@ -21,11 +21,11 @@ copied into the package next to the component: https://adoptium.net/ The icons java.svg, java_dark.svg, maven.svg and maven_dark.svg in -dev.lithe.plugin.java-support/icons/ come from the JetBrains IntelliJ Platform +io.github.lithe-idea.java-support/icons/ come from the JetBrains IntelliJ Platform Community repository (https://github.com/JetBrains/intellij-community), platform/icons/src/fileTypes and plugins/maven resources, licensed under the Apache License, Version 2.0 (a copy is in -dev.lithe.plugin.java-support/icons/LICENSE-APACHE-2.0.txt). +io.github.lithe-idea.java-support/icons/LICENSE-APACHE-2.0.txt). Copyright 2000-2024 JetBrains s.r.o. and contributors. spring-boot.svg and spring-boot_dark.svg are original Lithe artwork. diff --git a/README.md b/README.md index 0982bd1..aa2fe1f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,21 @@ # Java Support for Lithe -[Lithe](https://github.com/1lck/Lithe-IDEA) 的官方 Java 插件(`dev.lithe.plugin.java-support`): +[Lithe](https://github.com/1lck/Lithe-IDEA) 的 Java 插件(`io.github.lithe-idea.java-support`): 打包 Eclipse JDT Language Server、Lombok、java-debug、vscode-java-test 运行器和每个架构一份 Temurin JDK, 为 Java 项目提供补全、诊断、导航、运行/调试入口、测试运行和 Spring Boot / MyBatis 索引。 +它是普通插件(vendor 为 `Lithe Community`),插件包不带发布者签名。 -> English: The official Java plugin for Lithe. It bundles Eclipse JDT LS, Lombok, the java-debug and vscode-java-test -> runners and a per-architecture Temurin JDK, and provides Java language features, run/debug entry points, test runs -> and Spring Boot / MyBatis indexes. The Java rules live in a Rust domain crate and a plugin backend built on the -> published Lithe Rust plugin SDK. Maven and Gradle import settings come from the Maven and Gradle plugins through -> a function interface that Lithe Core relays between plugins. +> English: The Java plugin for Lithe, a regular plugin (vendor `Lithe Community`) whose package carries no publisher +> signature. It bundles Eclipse JDT LS, Lombok, the java-debug and vscode-java-test runners and a per-architecture +> Temurin JDK, and provides Java language features, run/debug entry points, test runs and Spring Boot / MyBatis +> indexes. The Java rules live in a Rust domain crate and a plugin backend built on the published Lithe Rust plugin +> SDK. Maven and Gradle import settings come from the Maven and Gradle plugins through a function interface that +> Lithe Core relays between plugins. > **进行中**:本仓库正在从 Lithe 主仓库拆分出来,目标是 Lithe 宿主(Rust Core 和 macOS 应用)不再包含任何 Java 专属逻辑, > Java 的领域规则全部由本插件提供,宿主只提供通用插件接口。插件后端还没有接入宿主:`plugin.json` 暂不声明 `backend`, -> 要等 `MIGRATION.md` 第 6 节列出的宿主插件接口合并。在那之前 Lithe 仍然内置 Java Support,本仓库发布的版本标为预发布。 +> 要等 `MIGRATION.md` 第 6 节列出的宿主插件接口合并。在那之前 Lithe 仍然内置 Java Support(旧 ID `dev.lithe.plugin.java-support`), +> 本仓库发布的版本标为预发布,原因见 `MIGRATION.md` 第 9 节。 ## 功能 @@ -35,33 +38,36 @@ 逐个调用,只接受落在 JDT LS 导入设置命名空间里的键,合并后交给语言服务器。 Maven 设置变化时调用 Java 导出的 `languageImport.settingsChanged`;Java 不会反过来调用正在调用它的插件。 细节见 `MIGRATION.md` 第 5 节。 -- **运行时只读**:插件包签名后在运行时只读。JDT LS、Lombok、java-debug、测试运行器和 JDK 都在构建阶段固定来源、校验哈希后放进包里, - 运行时状态只写宿主提供的状态目录。 +- **运行时只读**:插件包安装后在运行时只读。JDT LS、Lombok、java-debug、测试运行器和 JDK 都在构建阶段固定来源、校验哈希后放进包里, + 运行时状态只写宿主提供的状态目录,不写包目录。 ## 安装 -目前还不能从 Lithe Store 安装;Lithe 稳定版支持本插件所需的插件 API 之后,才会登记到商店索引(见 `MIGRATION.md` 第 9 节)。 -在 Lithe 开发版中,可以通过 **设置 → 插件 → ⚙ → 从磁盘安装插件…** 选择本地构建的包目录安装 -(发行版 Lithe 不加载未签名的开发包)。 +Lithe 不再区分官方插件和普通插件,所有插件都按普通插件处理:本插件不带发布者签名(`plugin.json` 的 `vendor.signatureRequirement` 为 `none`)。 +区别只在 [Lithe Store](https://github.com/Lithe-IDEA/Lithe-store) 怎样收录:Lithe-IDEA 组织里 `lithe-plugin-*` 仓库的稳定版(非预发布) +GitHub Release 由商店机器人自动跟踪并上架;组织之外的插件向 Lithe-store 提交 pull request,维护者审核后上架。 + +目前本仓库只发布预发布版,商店机器人会跳过,所以还不能从 Lithe Store 安装。当前版本的 Lithe 也会拒绝这个包: +它只允许 `dev.lithe.*` 插件使用 JDT 宿主集成(`languageServers[].hostIntegration`),只对带宿主验证过的官方来源的包接受短工具 ID `java`, +而本包两者都用到了;此外 Lithe 仍然内置旧 ID `dev.lithe.plugin.java-support` 的 Java Support。 +具体原因和转为正式发布的条件见 `MIGRATION.md` 第 9 节。下载的 ZIP 通过 **设置 → 插件** 的 ⚙ 菜单 → **从磁盘安装插件…** 安装。 ## 开发 ```text -dev.lithe.plugin.java-support/ # 插件包的静态部分:plugin.json、icons/、templates/,目录名必须等于插件 id +io.github.lithe-idea.java-support/ # 插件包的静态部分:plugin.json、icons/、templates/,目录名必须等于插件 id crates/java-domain/ # Java 领域规则(Rust),测试在各模块内和 tests/ 下 backend/ # 插件后端进程(lithe-java-backend),基于 Lithe Rust 插件 SDK fixtures/ # 与主仓库共享的契约样例(JSON) third_party/ # JDT LS 与 JDK 的来源地址和 SHA-256 sdk.lock.json # 后端链接的 Rust SDK:标签、提交、crate 归档的 SHA-256 -host-tools.lock.json # 签名器和校验器所用的 Lithe 提交 -scripts/ # 组装、校验、归档插件包,构建宿主工具,检查 SDK 锁 -.github/workflows/ci.yml # PR:格式、lint、测试、SDK 锁,以及 macOS 上的开发包构建 -.github/workflows/release.yml # 推送 v<版本> 标签:测试后签名并发布 GitHub Release +scripts/ # 组装、校验、归档插件包,检查 SDK 锁 +.github/workflows/ci.yml # PR:格式、lint、测试、SDK 锁,以及 macOS 上的打包任务(构建并归档两个架构) +.github/workflows/release.yml # 推送 v<版本> 标签:测试后打包并发布 GitHub Release(预发布) MIGRATION.md # 主仓库路径到本仓库的映射、待宿主接口清单、主仓库删除清单 ``` -Rust 部分需要 Rust 工具链和 Cargo;打包脚本需要 macOS、`zsh`、`curl`、`ditto`,构建宿主工具时还需要 `host-tools.lock.json` -所对应提交要求的 Swift 工具链。 +Rust 部分需要 Rust 工具链和 Cargo;打包脚本需要 macOS、`zsh`、`curl`、`ditto`,不需要 Xcode 或 Swift 工具链。 ```bash cargo fmt --all --check @@ -72,34 +78,34 @@ scripts/verify-sdk-lock.sh 所有测试都是有界、确定性的:不联网,不读全局时间,不占固定端口。 -构建本地未签名开发包(会下载并校验 JDT LS 与 JDK,体积较大): +构建并归档插件包(会下载并校验 JDT LS 与 JDK,体积较大)。本地开发、CI 和发布使用同一组命令,产出同一种归档: ```bash -scripts/build-package.sh --arch arm64 # 或 x86_64;打印包目录 .artifacts/package//dev.lithe.plugin.java-support -scripts/archive-package.sh --package <上一步打印的目录> --arch arm64 --development-unsigned +scripts/build-package.sh --arch arm64 # 或 x86_64;打印包目录 .artifacts/package//io.github.lithe-idea.java-support +scripts/archive-package.sh --package <上一步打印的目录> --arch arm64 # 写入 dist/Lithe-Java-Support-<版本>-darwin-{arm64,x64}.zip 和对应的 .sha256 ``` -签名发布包需要宿主工具(签名器和校验器,按 `host-tools.lock.json` 固定的 Lithe 提交构建)和发布私钥,只在发布工作流里进行: - -```bash -scripts/host-tools.sh --require-pinned-swift # 打印宿主工具所在目录 -``` +`build-package.sh` 会在输出包目录前校验它;`archive-package.sh` 把归档解开后再校验一次。单独校验一个包目录用 +`scripts/verify-package.sh --package <目录> --arch arm64|x86_64|universal`:它要求 `plugin.json` 的 `vendor.signatureRequirement` 为 `none`, +包里不能有 `lithe-plugin-signature.json`,并检查打包的 JDK 保留着上游的 Apple 代码签名。归档不需要签名密钥,也不调用任何签名工具。 `plugin.json` 的完整格式见 lithe-plugin-docs 里的 [插件契约](https://github.com/Lithe-IDEA/lithe-plugin-docs/blob/main/contract/v1/README.md)。 ## 发布新版本 -1. 修改 `dev.lithe.plugin.java-support/plugin.json` 的 `version`,合入 `main`。 +1. 修改 `io.github.lithe-idea.java-support/plugin.json` 的 `version`,合入 `main`。 2. 推送同名标签(带 `v` 前缀,必须等于清单版本): ```bash git tag v1.2.0 && git push origin v1.2.0 ``` -3. `Release` 工作流先在 Ubuntu 上跑 Rust 检查,再在 macOS 上构建并校验 arm64 与 x86_64 两个包;只有最后的签名与发布步骤拿 - `LITHE_PLUGIN_PACKAGE_PRIVATE_KEY`。发布资产是 `Lithe-Java-Support-<版本>-darwin-{arm64,x64}.zip` 和对应的 `.sha256`。 -4. 在 Lithe 稳定版不再内置 Java Support 之前,发布保持为预发布(`--prerelease`)。 +3. `Release` 工作流先在 Ubuntu 上跑 Rust 检查,再在 macOS 上构建、校验并归档 arm64 与 x86_64 两个包,然后发布。 + 发布资产是 `Lithe-Java-Support-<版本>-darwin-{arm64,x64}.zip` 和对应的 `.sha256`。没有任何步骤读取签名密钥,包也不带发布者签名。 +4. 发布保持为预发布(`--prerelease`):Lithe Store 的自动跟踪会跳过预发布,而目前的 Lithe 一是仍然内置旧 ID 的 Java Support, + 二是只允许 `dev.lithe.*` 插件使用 JDT 宿主集成、只对带官方来源的包接受短工具 ID `java`。等 Lithe 主仓库的阶段 E 完成 + (`MIGRATION.md` 第 8.2 节)后,去掉 `--prerelease`,商店就会自动上架稳定版。细节见 `MIGRATION.md` 第 9 节。 ## 许可 diff --git a/backend/src/plugin_functions.rs b/backend/src/plugin_functions.rs index 998c72d..ff549f0 100644 --- a/backend/src/plugin_functions.rs +++ b/backend/src/plugin_functions.rs @@ -436,12 +436,12 @@ mod tests { ); assert_eq!( invoke_params( - "dev.lithe.plugin.maven", + "io.github.lithe-idea.maven-build", &SETTINGS_FUNCTION, json!({ "workspaceRoot": "/work/app" }) ), json!({ - "pluginID": "dev.lithe.plugin.maven", + "pluginID": "io.github.lithe-idea.maven-build", "functionID": "languageImport.settings", "version": 1, "params": { "workspaceRoot": "/work/app" }, @@ -478,16 +478,19 @@ mod tests { #[test] fn providers_are_called_once_each_in_plugin_id_order() { let relay = FakeRelay::new(&[ - "dev.lithe.plugin.maven", - "dev.lithe.plugin.gradle", - "dev.lithe.plugin.maven", + "io.github.lithe-idea.maven-build", + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build", ]) - .answering("dev.lithe.plugin.maven", settings(json!({}))) - .answering("dev.lithe.plugin.gradle", settings(json!({}))); + .answering("io.github.lithe-idea.maven-build", settings(json!({}))) + .answering("io.github.lithe-idea.gradle-build", settings(json!({}))); collect(&relay); assert_eq!( relay.called_providers(), - ["dev.lithe.plugin.gradle", "dev.lithe.plugin.maven"] + [ + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build" + ] ); for (_, params) in relay.calls.borrow().iter() { assert_eq!(params, &json!({ "workspaceRoot": "/work/app" })); @@ -496,15 +499,18 @@ mod tests { #[test] fn answers_are_merged_in_plugin_id_order() { - let relay = FakeRelay::new(&["dev.lithe.plugin.maven", "dev.lithe.plugin.gradle"]) - .answering( - "dev.lithe.plugin.maven", - settings(json!({ "java.configuration.maven.userSettings": "/m/settings.xml" })), - ) - .answering( - "dev.lithe.plugin.gradle", - settings(json!({ "java.import.gradle.offline.enabled": true })), - ); + let relay = FakeRelay::new(&[ + "io.github.lithe-idea.maven-build", + "io.github.lithe-idea.gradle-build", + ]) + .answering( + "io.github.lithe-idea.maven-build", + settings(json!({ "java.configuration.maven.userSettings": "/m/settings.xml" })), + ) + .answering( + "io.github.lithe-idea.gradle-build", + settings(json!({ "java.import.gradle.offline.enabled": true })), + ); let contributions = collect(&relay); assert_eq!(contributions.status(), ContributedSettingsStatus::Settled); assert_eq!( @@ -527,18 +533,21 @@ mod tests { #[test] fn a_failing_provider_does_not_stop_the_others() { - let relay = FakeRelay::new(&["dev.lithe.plugin.gradle", "dev.lithe.plugin.maven"]) - .answering( - "dev.lithe.plugin.gradle", - Err(RelayFailure::new( - "plugin.host.timeout", - "/home/dev/.gradle is slow", - )), - ) - .answering( - "dev.lithe.plugin.maven", - settings(json!({ "java.import.maven.enabled": true })), - ); + let relay = FakeRelay::new(&[ + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build", + ]) + .answering( + "io.github.lithe-idea.gradle-build", + Err(RelayFailure::new( + "plugin.host.timeout", + "/home/dev/.gradle is slow", + )), + ) + .answering( + "io.github.lithe-idea.maven-build", + settings(json!({ "java.import.maven.enabled": true })), + ); let contributions = collect(&relay); assert_eq!(contributions.status(), ContributedSettingsStatus::Failed); assert_eq!( @@ -549,7 +558,7 @@ mod tests { assert_eq!( contributions.failures(), [( - "dev.lithe.plugin.gradle", + "io.github.lithe-idea.gradle-build", "The call failed (plugin.host.timeout)." )] ); @@ -557,26 +566,32 @@ mod tests { #[test] fn an_unusable_answer_marks_only_that_provider_failed() { - let relay = FakeRelay::new(&["dev.lithe.plugin.gradle", "dev.lithe.plugin.maven"]) - .answering( - "dev.lithe.plugin.gradle", - Ok(json!({ "settings": "offline" })), - ) - .answering( - "dev.lithe.plugin.maven", - settings(json!({ "java.import.maven.enabled": true })), - ); + let relay = FakeRelay::new(&[ + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build", + ]) + .answering( + "io.github.lithe-idea.gradle-build", + Ok(json!({ "settings": "offline" })), + ) + .answering( + "io.github.lithe-idea.maven-build", + settings(json!({ "java.import.maven.enabled": true })), + ); let contributions = collect(&relay); assert_eq!(contributions.status(), ContributedSettingsStatus::Failed); assert_eq!(contributions.failures().len(), 1); - assert_eq!(contributions.failures()[0].0, "dev.lithe.plugin.gradle"); + assert_eq!( + contributions.failures()[0].0, + "io.github.lithe-idea.gradle-build" + ); assert_eq!(contributions.fragments().len(), 1); } #[test] fn rejected_keys_are_logged_by_name_and_never_stored() { - let relay = FakeRelay::new(&["dev.lithe.plugin.maven"]).answering( - "dev.lithe.plugin.maven", + let relay = FakeRelay::new(&["io.github.lithe-idea.maven-build"]).answering( + "io.github.lithe-idea.maven-build", settings(json!({ "java.import.maven.enabled": true, "java.home": "/opt/other-jdk" @@ -614,7 +629,7 @@ mod tests { #[test] fn at_most_max_providers_are_asked() { let ids: Vec = (0..MAX_PROVIDERS + 4) - .map(|index| format!("dev.lithe.plugin.p{index:02}")) + .map(|index| format!("io.github.lithe-idea.p{index:02}")) .collect(); let relay = FakeRelay::new(&ids.iter().map(String::as_str).collect::>()); collect(&relay); @@ -623,16 +638,19 @@ mod tests { #[test] fn a_request_that_ran_out_of_time_fails_only_its_provider() { - let relay = FakeRelay::new(&["dev.lithe.plugin.gradle", "dev.lithe.plugin.maven"]) - .answering("dev.lithe.plugin.gradle", Err(cancelled())) - .answering( - "dev.lithe.plugin.maven", - settings(json!({ "java.import.maven.enabled": true })), - ); + let relay = FakeRelay::new(&[ + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build", + ]) + .answering("io.github.lithe-idea.gradle-build", Err(cancelled())) + .answering( + "io.github.lithe-idea.maven-build", + settings(json!({ "java.import.maven.enabled": true })), + ); let contributions = collect(&relay); assert_eq!( contributions.failures(), - [("dev.lithe.plugin.gradle", "The call timed out.")] + [("io.github.lithe-idea.gradle-build", "The call timed out.")] ); assert_eq!(contributions.fragments().len(), 1); } @@ -641,19 +659,25 @@ mod tests { fn cancelling_the_function_call_ends_the_collection() { let cancellation = Cancellation::new(); cancellation.cancel(); - let relay = FakeRelay::new(&["dev.lithe.plugin.maven"]); + let relay = FakeRelay::new(&["io.github.lithe-idea.maven-build"]); let outcome = collect_contributions(&relay, "/work/app", &cancellation, &|_| {}); assert!(outcome.is_err()); assert!(relay.called_providers().is_empty()); // Cancelled while a provider is being called: stop before the next one. let cancellation = Cancellation::new(); - let mut relay = FakeRelay::new(&["dev.lithe.plugin.gradle", "dev.lithe.plugin.maven"]) - .answering("dev.lithe.plugin.gradle", Err(cancelled())); + let mut relay = FakeRelay::new(&[ + "io.github.lithe-idea.gradle-build", + "io.github.lithe-idea.maven-build", + ]) + .answering("io.github.lithe-idea.gradle-build", Err(cancelled())); relay.cancel_on_invoke = Some(cancellation.clone()); let outcome = collect_contributions(&relay, "/work/app", &cancellation, &|_| {}); assert!(outcome.is_err()); - assert_eq!(relay.called_providers(), ["dev.lithe.plugin.gradle"]); + assert_eq!( + relay.called_providers(), + ["io.github.lithe-idea.gradle-build"] + ); } #[test] diff --git a/backend/tests/repository_pins.rs b/backend/tests/repository_pins.rs index feb654a..877f0c1 100644 --- a/backend/tests/repository_pins.rs +++ b/backend/tests/repository_pins.rs @@ -10,7 +10,7 @@ use serde_json::Value; use std::fs; use std::path::{Path, PathBuf}; -const PLUGIN_ID: &str = "dev.lithe.plugin.java-support"; +const PLUGIN_ID: &str = "io.github.lithe-idea.java-support"; fn repository_root() -> PathBuf { Path::new(env!("CARGO_MANIFEST_DIR")) @@ -65,14 +65,24 @@ fn cargo_resolves_the_sdk_commit_recorded_in_the_lock() { } #[test] -fn the_manifest_keeps_the_official_identity_and_declares_no_backend_yet() { +fn the_manifest_keeps_the_community_identity_and_declares_no_backend_yet() { let manifest = read_json(&format!("{PLUGIN_ID}/plugin.json")); assert_eq!(text(&manifest, "id"), PLUGIN_ID); assert_eq!(manifest["schemaVersion"], 2); - assert_eq!(text(&manifest["vendor"], "id"), "dev.lithe"); - assert_eq!( - text(&manifest["vendor"], "signatureRequirement"), - "publisherPackage" + // Lithe Store lists only unsigned community packages: the vendor is the + // organization namespace and the package carries no publisher signature, + // so nothing may require one or ask the host to check it. + let vendor = &manifest["vendor"]; + assert_eq!(text(vendor, "id"), "io.github.lithe-idea"); + assert_eq!(text(vendor, "displayName"), "Lithe Community"); + assert_eq!(text(vendor, "signatureRequirement"), "none"); + assert!( + vendor.get("bundledSignatureRequirement").is_none(), + "a community package has no bundled signature requirement" + ); + assert!( + manifest["requires"].get("packageTrust").is_none(), + "packageTrust only serves vendor.bundledSignatureRequirement" ); let version = text(&manifest, "version"); assert!( diff --git a/crates/java-domain/src/lsp/languages/jdt_contributions.rs b/crates/java-domain/src/lsp/languages/jdt_contributions.rs index d7632c7..5101612 100644 --- a/crates/java-domain/src/lsp/languages/jdt_contributions.rs +++ b/crates/java-domain/src/lsp/languages/jdt_contributions.rs @@ -265,11 +265,11 @@ mod tests { fn fragments_follow_plugin_id_order_not_arrival_order() { let mut contributions = Contributions::default(); contributions.record_settings( - "dev.lithe.plugin.maven", + "io.github.lithe-idea.maven-build", accepted(json!({ "java.import.maven.enabled": true })), ); contributions.record_settings( - "dev.lithe.plugin.gradle", + "io.github.lithe-idea.gradle-build", accepted(json!({ "java.import.gradle.offline.enabled": true })), ); assert_eq!( @@ -284,7 +284,7 @@ mod tests { #[test] fn a_change_replaces_the_providers_slot_and_removes_old_settings() { let mut contributions = Contributions::default(); - let maven = "dev.lithe.plugin.maven"; + let maven = "io.github.lithe-idea.maven-build"; contributions.record_settings( maven, accepted(json!({ @@ -307,16 +307,16 @@ mod tests { let mut contributions = Contributions::default(); assert_eq!(contributions.status(), ContributedSettingsStatus::Settled); - contributions.record_failure("dev.lithe.plugin.maven", "The call timed out."); + contributions.record_failure("io.github.lithe-idea.maven-build", "The call timed out."); assert_eq!(contributions.status(), ContributedSettingsStatus::Failed); assert_eq!( contributions.failures(), - [("dev.lithe.plugin.maven", "The call timed out.")] + [("io.github.lithe-idea.maven-build", "The call timed out.")] ); assert!(contributions.fragments().is_empty()); contributions.record_settings( - "dev.lithe.plugin.maven", + "io.github.lithe-idea.maven-build", accepted(json!({ "java.import.maven.enabled": true })), ); assert_eq!(contributions.status(), ContributedSettingsStatus::Settled); @@ -340,12 +340,12 @@ mod tests { fn forgetting_a_provider_drops_its_settings_and_its_failure() { let mut contributions = Contributions::default(); contributions.record_settings( - "dev.lithe.plugin.gradle", + "io.github.lithe-idea.gradle-build", accepted(json!({ "java.import.gradle.offline.enabled": true })), ); - contributions.record_failure("dev.lithe.plugin.maven", "The call failed."); - contributions.forget("dev.lithe.plugin.gradle"); - contributions.forget("dev.lithe.plugin.maven"); + contributions.record_failure("io.github.lithe-idea.maven-build", "The call failed."); + contributions.forget("io.github.lithe-idea.gradle-build"); + contributions.forget("io.github.lithe-idea.maven-build"); assert!(contributions.fragments().is_empty()); assert_eq!(contributions.status(), ContributedSettingsStatus::Settled); } diff --git a/host-tools.lock.json b/host-tools.lock.json deleted file mode 100644 index 7ea6db2..0000000 --- a/host-tools.lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "comment": "Lithe revision whose package tools sign and verify this plugin. LithePluginPackageSigner holds the trusted publisher keys and LitheOfficialPluginVerifier checks a package against the host's plugin contract, so both must come from Lithe itself. scripts/host-tools.sh builds them from this exact commit; update it when the plugin needs a newer contract.", - "repository": "https://github.com/1lck/Lithe-IDEA", - "revision": "1daaeb525831999ad518b4c6fd3b11b5b1b64b5a", - "products": ["LithePluginPackageSigner", "LitheOfficialPluginVerifier"] -} diff --git a/dev.lithe.plugin.java-support/icons/LICENSE-APACHE-2.0.txt b/io.github.lithe-idea.java-support/icons/LICENSE-APACHE-2.0.txt similarity index 100% rename from dev.lithe.plugin.java-support/icons/LICENSE-APACHE-2.0.txt rename to io.github.lithe-idea.java-support/icons/LICENSE-APACHE-2.0.txt diff --git a/dev.lithe.plugin.java-support/icons/NOTICE.txt b/io.github.lithe-idea.java-support/icons/NOTICE.txt similarity index 100% rename from dev.lithe.plugin.java-support/icons/NOTICE.txt rename to io.github.lithe-idea.java-support/icons/NOTICE.txt diff --git a/dev.lithe.plugin.java-support/icons/java.svg b/io.github.lithe-idea.java-support/icons/java.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/java.svg rename to io.github.lithe-idea.java-support/icons/java.svg diff --git a/dev.lithe.plugin.java-support/icons/java_dark.svg b/io.github.lithe-idea.java-support/icons/java_dark.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/java_dark.svg rename to io.github.lithe-idea.java-support/icons/java_dark.svg diff --git a/dev.lithe.plugin.java-support/icons/maven.svg b/io.github.lithe-idea.java-support/icons/maven.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/maven.svg rename to io.github.lithe-idea.java-support/icons/maven.svg diff --git a/dev.lithe.plugin.java-support/icons/maven_dark.svg b/io.github.lithe-idea.java-support/icons/maven_dark.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/maven_dark.svg rename to io.github.lithe-idea.java-support/icons/maven_dark.svg diff --git a/dev.lithe.plugin.java-support/icons/spring-boot.svg b/io.github.lithe-idea.java-support/icons/spring-boot.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/spring-boot.svg rename to io.github.lithe-idea.java-support/icons/spring-boot.svg diff --git a/dev.lithe.plugin.java-support/icons/spring-boot_dark.svg b/io.github.lithe-idea.java-support/icons/spring-boot_dark.svg similarity index 100% rename from dev.lithe.plugin.java-support/icons/spring-boot_dark.svg rename to io.github.lithe-idea.java-support/icons/spring-boot_dark.svg diff --git a/dev.lithe.plugin.java-support/plugin.json b/io.github.lithe-idea.java-support/plugin.json similarity index 98% rename from dev.lithe.plugin.java-support/plugin.json rename to io.github.lithe-idea.java-support/plugin.json index 7bcd18b..3b68cf8 100644 --- a/dev.lithe.plugin.java-support/plugin.json +++ b/io.github.lithe-idea.java-support/plugin.json @@ -1,15 +1,14 @@ { "schemaVersion": 2, - "id": "dev.lithe.plugin.java-support", + "id": "io.github.lithe-idea.java-support", "displayName": "Java Support", "version": "1.1.0", "pluginAPIVersion": 4, - "requires": {"debugAdapters": 1, "languages": 1, "languageServers": 1, "serverProcess": 1, "settings": 2, "projectGenerators": 1, "packageTrust": 1, "toolDefinitions": 1, "executableResolution": 2}, + "requires": {"debugAdapters": 1, "languages": 1, "languageServers": 1, "serverProcess": 1, "settings": 2, "projectGenerators": 1, "toolDefinitions": 1, "executableResolution": 2}, "vendor": { - "id": "dev.lithe", - "displayName": "Lithe", - "signatureRequirement": "publisherPackage", - "bundledSignatureRequirement": "sameTeamAsHost" + "id": "io.github.lithe-idea", + "displayName": "Lithe Community", + "signatureRequirement": "none" }, "permissions": ["languageServer.launch", "project.generate", "debug.launch", "debug.attach"], "activationEvents": ["onLanguage:java", "onDebug:java"], diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-groovy/build.gradle b/io.github.lithe-idea.java-support/templates/java/gradle-groovy/build.gradle similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-groovy/build.gradle rename to io.github.lithe-idea.java-support/templates/java/gradle-groovy/build.gradle diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-groovy/dot-gitignore b/io.github.lithe-idea.java-support/templates/java/gradle-groovy/dot-gitignore similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-groovy/dot-gitignore rename to io.github.lithe-idea.java-support/templates/java/gradle-groovy/dot-gitignore diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-groovy/settings.gradle b/io.github.lithe-idea.java-support/templates/java/gradle-groovy/settings.gradle similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-groovy/settings.gradle rename to io.github.lithe-idea.java-support/templates/java/gradle-groovy/settings.gradle diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-kotlin/build.gradle.kts b/io.github.lithe-idea.java-support/templates/java/gradle-kotlin/build.gradle.kts similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-kotlin/build.gradle.kts rename to io.github.lithe-idea.java-support/templates/java/gradle-kotlin/build.gradle.kts diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-kotlin/dot-gitignore b/io.github.lithe-idea.java-support/templates/java/gradle-kotlin/dot-gitignore similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-kotlin/dot-gitignore rename to io.github.lithe-idea.java-support/templates/java/gradle-kotlin/dot-gitignore diff --git a/dev.lithe.plugin.java-support/templates/java/gradle-kotlin/settings.gradle.kts b/io.github.lithe-idea.java-support/templates/java/gradle-kotlin/settings.gradle.kts similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/gradle-kotlin/settings.gradle.kts rename to io.github.lithe-idea.java-support/templates/java/gradle-kotlin/settings.gradle.kts diff --git a/dev.lithe.plugin.java-support/templates/java/maven/dot-gitignore b/io.github.lithe-idea.java-support/templates/java/maven/dot-gitignore similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/maven/dot-gitignore rename to io.github.lithe-idea.java-support/templates/java/maven/dot-gitignore diff --git a/dev.lithe.plugin.java-support/templates/java/maven/pom.xml b/io.github.lithe-idea.java-support/templates/java/maven/pom.xml similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/maven/pom.xml rename to io.github.lithe-idea.java-support/templates/java/maven/pom.xml diff --git a/dev.lithe.plugin.java-support/templates/java/plain-empty/src/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/plain-empty/src/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/plain-empty/src/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/plain-empty/src/dot-gitkeep diff --git a/dev.lithe.plugin.java-support/templates/java/plain-sample/src/Main.java b/io.github.lithe-idea.java-support/templates/java/plain-sample/src/Main.java similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/plain-sample/src/Main.java rename to io.github.lithe-idea.java-support/templates/java/plain-sample/src/Main.java diff --git a/dev.lithe.plugin.java-support/templates/java/plain/dot-gitignore b/io.github.lithe-idea.java-support/templates/java/plain/dot-gitignore similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/plain/dot-gitignore rename to io.github.lithe-idea.java-support/templates/java/plain/dot-gitignore diff --git a/dev.lithe.plugin.java-support/templates/java/standard-empty/src/main/java/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/standard-empty/src/main/java/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-empty/src/main/java/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/standard-empty/src/main/java/dot-gitkeep diff --git a/dev.lithe.plugin.java-support/templates/java/standard-empty/src/main/resources/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/standard-empty/src/main/resources/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-empty/src/main/resources/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/standard-empty/src/main/resources/dot-gitkeep diff --git a/dev.lithe.plugin.java-support/templates/java/standard-empty/src/test/java/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/standard-empty/src/test/java/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-empty/src/test/java/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/standard-empty/src/test/java/dot-gitkeep diff --git a/dev.lithe.plugin.java-support/templates/java/standard-sample-main/Main.java b/io.github.lithe-idea.java-support/templates/java/standard-sample-main/Main.java similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-sample-main/Main.java rename to io.github.lithe-idea.java-support/templates/java/standard-sample-main/Main.java diff --git a/dev.lithe.plugin.java-support/templates/java/standard-sample/src/main/resources/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/standard-sample/src/main/resources/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-sample/src/main/resources/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/standard-sample/src/main/resources/dot-gitkeep diff --git a/dev.lithe.plugin.java-support/templates/java/standard-sample/src/test/java/dot-gitkeep b/io.github.lithe-idea.java-support/templates/java/standard-sample/src/test/java/dot-gitkeep similarity index 100% rename from dev.lithe.plugin.java-support/templates/java/standard-sample/src/test/java/dot-gitkeep rename to io.github.lithe-idea.java-support/templates/java/standard-sample/src/test/java/dot-gitkeep diff --git a/scripts/archive-package.sh b/scripts/archive-package.sh index c6425d2..1172561 100755 --- a/scripts/archive-package.sh +++ b/scripts/archive-package.sh @@ -2,35 +2,26 @@ set -euo pipefail -# Signs and archives a package directory built by scripts/build-package.sh. +# Archives a package directory built by scripts/build-package.sh into the +# unsigned plugin archive that Lithe Store lists. The package carries no +# signature; plugin.json declares vendor.signatureRequirement "none". # -# --sign reads the publisher key from LITHE_PLUGIN_PACKAGE_PRIVATE_KEY and -# signs with the Lithe signer from scripts/host-tools.sh; only the release -# workflow's publishing step has that key. --development-unsigned archives -# the package without a signature; only development builds of Lithe install -# such a package, so its file name says so. -# -# The archive is dist/Lithe-Java-Support--darwin-.zip -# (with -unsigned before .zip for development archives), created with -# `ditto --keepParent` so it holds the package directory itself. The archive -# is extracted again and re-verified, and dist/.sha256 records its +# The archive is dist/Lithe-Java-Support--darwin-.zip, +# created with `ditto --keepParent` so it holds the package directory itself. +# Development and release builds use the same archive. The archive is +# extracted again and re-verified, and dist/.sha256 records its # SHA-256. Prints " dist/". ROOT_DIR="${0:A:h:h}" -PLUGIN_ID="dev.lithe.plugin.java-support" +PLUGIN_ID="io.github.lithe-idea.java-support" PACKAGE="" ARCH="" -HOST_TOOLS="" -MODE="" while [[ $# -gt 0 ]]; do case "$1" in --package) PACKAGE="$2"; shift 2 ;; --arch) ARCH="$2"; shift 2 ;; - --host-tools) HOST_TOOLS="$2"; shift 2 ;; - --sign) MODE="sign"; shift ;; - --development-unsigned) MODE="unsigned"; shift ;; - *) print -u2 -- "Usage: $0 --package directory --arch arm64|x86_64 (--sign --host-tools bin-directory | --development-unsigned)"; exit 2 ;; + *) print -u2 -- "Usage: $0 --package directory --arch arm64|x86_64"; exit 2 ;; esac done [[ -d "$PACKAGE" && "${PACKAGE:A:t}" == "$PLUGIN_ID" ]] || { @@ -44,29 +35,7 @@ case "$ARCH" in esac version=$(/usr/bin/plutil -extract version raw -o - "$PACKAGE/plugin.json") -case "$MODE" in - sign) - [[ -n "$HOST_TOOLS" ]] || { print -u2 -- "--sign needs --host-tools"; exit 2; } - [[ -n "${LITHE_PLUGIN_PACKAGE_PRIVATE_KEY:-}" ]] || { - print -u2 -- "Configure LITHE_PLUGIN_PACKAGE_PRIVATE_KEY to sign the Java Support package" - exit 1 - } - rm -f "$PACKAGE/lithe-plugin-signature.json" - print -rn -- "$LITHE_PLUGIN_PACKAGE_PRIVATE_KEY" | "$HOST_TOOLS/LithePluginPackageSigner" "$PACKAGE" - asset="Lithe-Java-Support-$version-$platform.zip" - verify_args=(--require-signature) - ;; - unsigned) - [[ ! -f "$PACKAGE/lithe-plugin-signature.json" ]] || { - print -u2 -- "The package is already signed; rebuild it before a development archive" - exit 1 - } - asset="Lithe-Java-Support-$version-$platform-unsigned.zip" - verify_args=() - ;; - *) print -u2 -- "Choose --sign or --development-unsigned"; exit 2 ;; -esac -[[ -z "$HOST_TOOLS" ]] || verify_args+=(--host-tools "$HOST_TOOLS") +asset="Lithe-Java-Support-$version-$platform.zip" dist="$ROOT_DIR/dist" mkdir -p "$dist" @@ -74,9 +43,8 @@ rm -f "$dist/$asset" "$dist/$asset.sha256" /usr/bin/ditto -c -k --keepParent "$PACKAGE" "$dist/$asset" # Verify what users download, not the directory it was made from. -# The check directory stays inside the repository: the official verifier -# rejects packages under a symbolically linked path such as $TMPDIR -# (/var is /private/var on macOS). +# The check directory stays under .artifacts with the other build outputs +# (.gitignore excludes it) instead of $TMPDIR. extracted="$ROOT_DIR/.artifacts/archive-check/$platform" rm -rf "$extracted" mkdir -p "$extracted" @@ -87,7 +55,7 @@ entries=("$extracted"/*(DN:t)) print -u2 -- "$asset must contain only $PLUGIN_ID/, found: ${entries[*]}" exit 1 } -"$ROOT_DIR/scripts/verify-package.sh" --package "$extracted/$PLUGIN_ID" --arch "$ARCH" "${verify_args[@]}" +"$ROOT_DIR/scripts/verify-package.sh" --package "$extracted/$PLUGIN_ID" --arch "$ARCH" checksum=$(/usr/bin/shasum -a 256 "$dist/$asset" | cut -d' ' -f1) print -r -- "$checksum" > "$dist/$asset.sha256" diff --git a/scripts/assemble-package.sh b/scripts/assemble-package.sh index 689377b..5237253 100755 --- a/scripts/assemble-package.sh +++ b/scripts/assemble-package.sh @@ -13,7 +13,7 @@ set -euo pipefail # repository; see MIGRATION.md. ROOT_DIR="${0:A:h:h}" -PLUGIN_DIR="$ROOT_DIR/dev.lithe.plugin.java-support" +PLUGIN_DIR="$ROOT_DIR/io.github.lithe-idea.java-support" OUTPUT_DIR="" ARCH="" @@ -79,7 +79,7 @@ launcher=$(/usr/bin/plutil -extract languageServers.0.launch.entry raw "$PLUGIN_ test_runner=$(/usr/bin/plutil -extract languageServers.0.hostIntegration.resources.testRunner raw "$PLUGIN_DIR/plugin.json") for declared in "$launcher" "$test_runner" language-server/lombok/lombok.jar; do [[ -f "$OUTPUT_DIR/$declared" ]] || { - print -u2 -- "Java Support declares $declared, which the assembled package does not contain. Update dev.lithe.plugin.java-support/plugin.json for the pinned JDT LS version." + print -u2 -- "Java Support declares $declared, which the assembled package does not contain. Update io.github.lithe-idea.java-support/plugin.json for the pinned JDT LS version." exit 1 } done diff --git a/scripts/build-package.sh b/scripts/build-package.sh index 0ce5756..173caa2 100755 --- a/scripts/build-package.sh +++ b/scripts/build-package.sh @@ -2,25 +2,23 @@ set -euo pipefail -# Builds the unsigned Java Support package directory for one architecture: -# copies plugin.json, assembles the pinned third-party resources next to it +# Builds the Java Support package directory for one architecture: copies +# plugin.json, assembles the pinned third-party resources next to it # (scripts/assemble-package.sh) and verifies the result # (scripts/verify-package.sh). Prints the package directory, -# .artifacts/package//dev.lithe.plugin.java-support. +# .artifacts/package//io.github.lithe-idea.java-support. # -# Signing and archiving are a separate step (scripts/archive-package.sh) so -# that the release workflow only exposes the signing key to that step. +# This only builds the directory. Archiving it into the release asset is the +# separate step scripts/archive-package.sh. ROOT_DIR="${0:A:h:h}" -PLUGIN_ID="dev.lithe.plugin.java-support" +PLUGIN_ID="io.github.lithe-idea.java-support" ARCH="" -HOST_TOOLS="" while [[ $# -gt 0 ]]; do case "$1" in --arch) ARCH="$2"; shift 2 ;; - --host-tools) HOST_TOOLS="$2"; shift 2 ;; - *) print -u2 -- "Usage: $0 --arch arm64|x86_64 [--host-tools bin-directory]"; exit 2 ;; + *) print -u2 -- "Usage: $0 --arch arm64|x86_64"; exit 2 ;; esac done # Each release asset targets one macOS architecture; the store lists them as @@ -36,7 +34,5 @@ mkdir -p "$package_dir" cp "$ROOT_DIR/$PLUGIN_ID/plugin.json" "$package_dir/plugin.json" "$ROOT_DIR/scripts/assemble-package.sh" --output "$package_dir" --arch "$ARCH" >&2 -verify_args=(--package "$package_dir" --arch "$ARCH") -[[ -z "$HOST_TOOLS" ]] || verify_args+=(--host-tools "$HOST_TOOLS") -"$ROOT_DIR/scripts/verify-package.sh" "${verify_args[@]}" +"$ROOT_DIR/scripts/verify-package.sh" --package "$package_dir" --arch "$ARCH" print -r -- "$package_dir" diff --git a/scripts/host-tools.sh b/scripts/host-tools.sh deleted file mode 100755 index a44a8aa..0000000 --- a/scripts/host-tools.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/bin/zsh - -set -euo pipefail - -# Builds the Lithe package tools this plugin is signed and verified with: -# LithePluginPackageSigner (it holds the trusted publisher keys) and -# LitheOfficialPluginVerifier (it applies the host's plugin contract). Both -# come from the Lithe revision pinned in host-tools.lock.json, fetched into -# .artifacts/host-tools//source; nothing outside this repository is -# written. Prints the directory that holds the two executables. -# -# LITHE_HOST_SOURCE may name a local Lithe clone to fetch the revision from -# instead of the network; the clone is only read. -# -# The pinned revision names its Swift compiler in .swift-version. A different -# compiler only prints a warning, unless --require-pinned-swift is given (CI -# and releases use it). - -ROOT_DIR="${0:A:h:h}" -LOCK="$ROOT_DIR/host-tools.lock.json" -REQUIRE_PINNED_SWIFT=false - -while [[ $# -gt 0 ]]; do - case "$1" in - --require-pinned-swift) REQUIRE_PINNED_SWIFT=true; shift ;; - *) print -u2 -- "Usage: $0 [--require-pinned-swift]"; exit 2 ;; - esac -done - -repository=$(/usr/bin/plutil -extract repository raw -o - "$LOCK") -revision=$(/usr/bin/plutil -extract revision raw -o - "$LOCK") -[[ "$revision" =~ '^[0-9a-f]{40}$' ]] || { - print -u2 -- "host-tools.lock.json must pin a full commit: $revision" - exit 1 -} -work="$ROOT_DIR/.artifacts/host-tools/$revision" -source_dir="$work/source" - -if [[ "$(git -C "$source_dir" rev-parse HEAD 2>/dev/null || true)" != "$revision" ]]; then - rm -rf "$source_dir" - mkdir -p "$source_dir" - git -C "$source_dir" init --quiet - git -C "$source_dir" fetch --quiet --depth 1 "${LITHE_HOST_SOURCE:-$repository}" "$revision" - git -C "$source_dir" checkout --quiet --detach FETCH_HEAD -fi -[[ "$(git -C "$source_dir" rev-parse HEAD)" == "$revision" ]] || { - print -u2 -- "Fetched Lithe source is not $revision" - exit 1 -} - -expected_swift=$(<"$source_dir/.swift-version") -actual_swift=$(swift --version 2>/dev/null | sed -nE 's/.*Swift version ([0-9]+\.[0-9]+(\.[0-9]+)?).*/\1/p' | head -n 1) -if [[ "$actual_swift" != "$expected_swift" ]]; then - message="Lithe $revision builds with Swift $expected_swift, found ${actual_swift:-no Swift}" - [[ "$REQUIRE_PINNED_SWIFT" == false ]] || { print -u2 -- "$message"; exit 1; } - print -u2 -- "warning: $message" -fi - -case "$(uname -m)" in - arm64) triple="arm64-apple-macosx" ;; - x86_64) triple="x86_64-apple-macosx" ;; - *) print -u2 -- "Unsupported host architecture: $(uname -m)"; exit 1 ;; -esac -# Same flags Lithe uses for these products; building them alone keeps the -# application and its Rust Core out of the build. -swift_args=( - --package-path "$source_dir" - --scratch-path "$work/build" - --triple "$triple" - -Xswiftc -Xfrontend - -Xswiftc -disable-round-trip-debug-types -) -for product in LithePluginPackageSigner LitheOfficialPluginVerifier; do - swift build "${swift_args[@]}" --product "$product" >&2 -done -bin_dir=$(swift build "${swift_args[@]}" --show-bin-path) -for product in LithePluginPackageSigner LitheOfficialPluginVerifier; do - [[ -x "$bin_dir/$product" ]] || { - print -u2 -- "Lithe host tool was not built: $bin_dir/$product" - exit 1 - } -done -print -r -- "$bin_dir" diff --git a/scripts/verify-package.sh b/scripts/verify-package.sh index 6ff549a..245913a 100755 --- a/scripts/verify-package.sh +++ b/scripts/verify-package.sh @@ -2,32 +2,25 @@ set -euo pipefail -# Verifies an assembled Java Support package directory before it is signed or -# archived: -# - plugin.json is the repository manifest, unchanged; +# Verifies an assembled Java Support package directory before it is archived: +# - plugin.json is the repository manifest, unchanged, and declares a +# plugin without a publisher signature (vendor.signatureRequirement "none"); # - the package holds only the declared top-level entries and no symbolic # links, and nothing outside runtime/ is executable; # - every file plugin.json names for the language server exists; # - the packaged JDK is the requested architecture and keeps its upstream -# code signature (the publisher signature alone does not prove macOS can -# launch it). -# With --host-tools it also runs Lithe's official package verifier and, when -# the package is signed, checks the publisher signature. +# code signature (macOS only launches the JDK if it does). ROOT_DIR="${0:A:h:h}" -PLUGIN_ID="dev.lithe.plugin.java-support" +PLUGIN_ID="io.github.lithe-idea.java-support" PACKAGE="" ARCH="" -HOST_TOOLS="" -REQUIRE_SIGNATURE=false while [[ $# -gt 0 ]]; do case "$1" in --package) PACKAGE="$2"; shift 2 ;; --arch) ARCH="$2"; shift 2 ;; - --host-tools) HOST_TOOLS="$2"; shift 2 ;; - --require-signature) REQUIRE_SIGNATURE=true; shift ;; - *) print -u2 -- "Usage: $0 --package directory --arch arm64|x86_64|universal [--host-tools bin-directory] [--require-signature]"; exit 2 ;; + *) print -u2 -- "Usage: $0 --package directory --arch arm64|x86_64|universal"; exit 2 ;; esac done [[ -d "$PACKAGE" ]] || { print -u2 -- "--package must name an assembled package directory"; exit 2; } @@ -47,10 +40,12 @@ cmp -s "$manifest" "$ROOT_DIR/$PLUGIN_ID/plugin.json" || fail "plugin.json differs from $PLUGIN_ID/plugin.json" [[ "$(/usr/bin/plutil -extract id raw -o - "$manifest")" == "$PLUGIN_ID" ]] || fail "plugin.json does not declare $PLUGIN_ID" +[[ "$(/usr/bin/plutil -extract vendor.signatureRequirement raw -o - "$manifest")" == "none" ]] || + fail "plugin.json must declare vendor.signatureRequirement none; Lithe Store lists only packages without a publisher signature" [[ "${PACKAGE:A:t}" == "$PLUGIN_ID" ]] || fail "the package directory must be named $PLUGIN_ID" -allowed=(plugin.json icons templates language-server runtime lithe-plugin-signature.json) +allowed=(plugin.json icons templates language-server runtime) for entry in "$PACKAGE"/*(DN); do (( ${allowed[(Ie)${entry:t}]} )) || fail "undeclared top-level entry ${entry:t}" done @@ -92,14 +87,4 @@ for runtime_arch in "${runtime_architectures[@]}"; do fail "$runtime/lib/server/libjvm.dylib lost its upstream code signature" done -signature="$PACKAGE/lithe-plugin-signature.json" -if [[ "$REQUIRE_SIGNATURE" == true && ! -f "$signature" ]]; then - fail "the package is not publisher-signed" -fi -if [[ -n "$HOST_TOOLS" ]]; then - "$HOST_TOOLS/LitheOfficialPluginVerifier" "$PACKAGE" - if [[ -f "$signature" ]]; then - "$HOST_TOOLS/LithePluginPackageSigner" --verify "$PACKAGE" - fi -fi print -u2 -- "Verified Java Support package $PACKAGE ($ARCH)"