biucingcli 0.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- biucingcli/__init__.py +5 -0
- biucingcli/cli.py +849 -0
- biucingcli/template_data/android/template/.editorconfig +9 -0
- biucingcli/template_data/android/template/.gitignore +26 -0
- biucingcli/template_data/android/template/.mise.toml +3 -0
- biucingcli/template_data/android/template/Brewfile +6 -0
- biucingcli/template_data/android/template/Makefile +103 -0
- biucingcli/template_data/android/template/README.md +163 -0
- biucingcli/template_data/android/template/app/build.gradle.kts +178 -0
- biucingcli/template_data/android/template/app/proguard-rules.pro +1 -0
- biucingcli/template_data/android/template/app/src/androidTest/java/app/HomeRouteUiTest.kt +21 -0
- biucingcli/template_data/android/template/app/src/main/AndroidManifest.xml +18 -0
- biucingcli/template_data/android/template/app/src/main/java/app/MainActivity.kt +36 -0
- biucingcli/template_data/android/template/app/src/main/res/values/strings.xml +4 -0
- biucingcli/template_data/android/template/app/src/main/res/values/themes.xml +8 -0
- biucingcli/template_data/android/template/app/src/test/java/app/AppSmokeTest.kt +19 -0
- biucingcli/template_data/android/template/build.gradle.kts +27 -0
- biucingcli/template_data/android/template/core/designsystem/build.gradle.kts +33 -0
- biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/Components.kt +75 -0
- biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/DesignTokens.kt +23 -0
- biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/Theme.kt +110 -0
- biucingcli/template_data/android/template/core/model/build.gradle.kts +26 -0
- biucingcli/template_data/android/template/core/model/src/main/java/model/Greeting.kt +6 -0
- biucingcli/template_data/android/template/core/model/src/test/java/model/GreetingTest.kt +16 -0
- biucingcli/template_data/android/template/core/network/build.gradle.kts +26 -0
- biucingcli/template_data/android/template/core/network/src/main/java/network/AppEnvironment.kt +17 -0
- biucingcli/template_data/android/template/core/testing/build.gradle.kts +27 -0
- biucingcli/template_data/android/template/core/testing/src/main/java/testing/FakeAppEnvironmentProvider.kt +13 -0
- biucingcli/template_data/android/template/docs/release-delivery.md +68 -0
- biucingcli/template_data/android/template/docs/release-signing.properties.example +20 -0
- biucingcli/template_data/android/template/fastlane/.env.example +22 -0
- biucingcli/template_data/android/template/fastlane/Appfile +1 -0
- biucingcli/template_data/android/template/fastlane/Fastfile +121 -0
- biucingcli/template_data/android/template/feature/home/build.gradle.kts +35 -0
- biucingcli/template_data/android/template/feature/home/src/main/java/home/HomeRoute.kt +38 -0
- biucingcli/template_data/android/template/feature/settings/build.gradle.kts +34 -0
- biucingcli/template_data/android/template/feature/settings/src/main/java/settings/SettingsRoute.kt +35 -0
- biucingcli/template_data/android/template/gradle/libs.versions.toml +35 -0
- biucingcli/template_data/android/template/gradle/verification-metadata.xml +3462 -0
- biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.jar +0 -0
- biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.jar.sha256 +1 -0
- biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.properties +10 -0
- biucingcli/template_data/android/template/gradle.properties +4 -0
- biucingcli/template_data/android/template/gradlew +252 -0
- biucingcli/template_data/android/template/gradlew.bat +94 -0
- biucingcli/template_data/android/template/scripts/artifact-info +11 -0
- biucingcli/template_data/android/template/scripts/bootstrap +17 -0
- biucingcli/template_data/android/template/scripts/doctor +133 -0
- biucingcli/template_data/android/template/scripts/setup-android-sdk +23 -0
- biucingcli/template_data/android/template/scripts/sync-gradle-wrapper +19 -0
- biucingcli/template_data/android/template/scripts/verify-gradle-supply-chain +61 -0
- biucingcli/template_data/android/template/scripts/verify-release-artifact +104 -0
- biucingcli/template_data/android/template/settings.gradle.kts +25 -0
- biucingcli/template_data/android/template.json +146 -0
- biucingcli/template_data/apple/template/.gitignore +28 -0
- biucingcli/template_data/apple/template/.mise.toml +4 -0
- biucingcli/template_data/apple/template/.swiftformat +10 -0
- biucingcli/template_data/apple/template/.swiftlint.yml +33 -0
- biucingcli/template_data/apple/template/App/Config/ProjectDescriptionHelpers/Module.swift +6 -0
- biucingcli/template_data/apple/template/App/Config/XCConfig/Base.xcconfig +4 -0
- biucingcli/template_data/apple/template/App/Project.swift +66 -0
- biucingcli/template_data/apple/template/App/Targets/App/Resources/.gitkeep +1 -0
- biucingcli/template_data/apple/template/App/Targets/App/Sources/AppEntry.swift +9 -0
- biucingcli/template_data/apple/template/App/Targets/App/Sources/HomeView.swift +18 -0
- biucingcli/template_data/apple/template/App/Targets/App/Sources/HomeViewModel.swift +38 -0
- biucingcli/template_data/apple/template/App/Targets/AppTests/Sources/AppTests.swift +59 -0
- biucingcli/template_data/apple/template/Brewfile +8 -0
- biucingcli/template_data/apple/template/Makefile +128 -0
- biucingcli/template_data/apple/template/Packages/AppServices/Package.swift +20 -0
- biucingcli/template_data/apple/template/Packages/AppServices/Sources/AppServices/StarterMetadata.swift +52 -0
- biucingcli/template_data/apple/template/Packages/DesignSystem/Package.swift +20 -0
- biucingcli/template_data/apple/template/Packages/DesignSystem/Sources/DesignSystem/Theme.swift +8 -0
- biucingcli/template_data/apple/template/README.md +133 -0
- biucingcli/template_data/apple/template/Tuist.swift +8 -0
- biucingcli/template_data/apple/template/Workspace.swift +11 -0
- biucingcli/template_data/apple/template/docs/release-delivery.md +55 -0
- biucingcli/template_data/apple/template/fastlane/.env.example +20 -0
- biucingcli/template_data/apple/template/fastlane/Appfile +3 -0
- biucingcli/template_data/apple/template/fastlane/Fastfile +126 -0
- biucingcli/template_data/apple/template/fastlane/Matchfile +7 -0
- biucingcli/template_data/apple/template/scripts/bootstrap +9 -0
- biucingcli/template_data/apple/template/scripts/doctor +163 -0
- biucingcli/template_data/apple/template/scripts/setup-xcode +6 -0
- biucingcli/template_data/apple/template/scripts/test-destination +42 -0
- biucingcli/template_data/apple/template/scripts/verify-release-identity +88 -0
- biucingcli/template_data/apple/template.json +110 -0
- biucingcli/template_data/frontend/template/.dockerignore +8 -0
- biucingcli/template_data/frontend/template/.env.example +1 -0
- biucingcli/template_data/frontend/template/.gitignore +7 -0
- biucingcli/template_data/frontend/template/.npmrc +1 -0
- biucingcli/template_data/frontend/template/.prettierignore +2 -0
- biucingcli/template_data/frontend/template/.prettierrc.json +4 -0
- biucingcli/template_data/frontend/template/Dockerfile +25 -0
- biucingcli/template_data/frontend/template/Dockerfile.dev +35 -0
- biucingcli/template_data/frontend/template/Dockerfile.dev.full +40 -0
- biucingcli/template_data/frontend/template/Makefile +137 -0
- biucingcli/template_data/frontend/template/README.md +146 -0
- biucingcli/template_data/frontend/template/compose.dev.yaml +29 -0
- biucingcli/template_data/frontend/template/eslint.config.js +27 -0
- biucingcli/template_data/frontend/template/index.html +12 -0
- biucingcli/template_data/frontend/template/nginx.conf +11 -0
- biucingcli/template_data/frontend/template/package.json +50 -0
- biucingcli/template_data/frontend/template/playwright.production.config.ts +21 -0
- biucingcli/template_data/frontend/template/playwright.smoke.config.ts +19 -0
- biucingcli/template_data/frontend/template/pnpm-lock.yaml +4054 -0
- biucingcli/template_data/frontend/template/public/.gitkeep +1 -0
- biucingcli/template_data/frontend/template/scripts/browser-smoke-production +55 -0
- biucingcli/template_data/frontend/template/scripts/doctor +46 -0
- biucingcli/template_data/frontend/template/src/App.test.tsx +18 -0
- biucingcli/template_data/frontend/template/src/App.tsx +5 -0
- biucingcli/template_data/frontend/template/src/components/MetricCard.tsx +14 -0
- biucingcli/template_data/frontend/template/src/components/TaskPanel.tsx +32 -0
- biucingcli/template_data/frontend/template/src/config/env.ts +3 -0
- biucingcli/template_data/frontend/template/src/hooks/useProjectOverview.ts +24 -0
- biucingcli/template_data/frontend/template/src/index.css +208 -0
- biucingcli/template_data/frontend/template/src/main.tsx +11 -0
- biucingcli/template_data/frontend/template/src/pages/HomePage.tsx +60 -0
- biucingcli/template_data/frontend/template/src/router/AppRouter.tsx +14 -0
- biucingcli/template_data/frontend/template/src/services/api/client.ts +33 -0
- biucingcli/template_data/frontend/template/src/services/projectOverview.ts +39 -0
- biucingcli/template_data/frontend/template/src/test/setup.ts +1 -0
- biucingcli/template_data/frontend/template/src/types/projectOverview.ts +22 -0
- biucingcli/template_data/frontend/template/src/vite-env.d.ts +9 -0
- biucingcli/template_data/frontend/template/tests/browser-smoke.spec.ts +16 -0
- biucingcli/template_data/frontend/template/tests/production-browser-smoke.spec.ts +22 -0
- biucingcli/template_data/frontend/template/tsconfig.json +21 -0
- biucingcli/template_data/frontend/template/vite.config.ts +12 -0
- biucingcli/template_data/frontend/template.json +81 -0
- biucingcli/template_data/harmonyos/template/.gitignore +21 -0
- biucingcli/template_data/harmonyos/template/.mise.toml +2 -0
- biucingcli/template_data/harmonyos/template/AppScope/app.json5 +10 -0
- biucingcli/template_data/harmonyos/template/AppScope/resources/base/element/string.json +8 -0
- biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/background.svg +3 -0
- biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/foreground.svg +4 -0
- biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/layered_image.json +6 -0
- biucingcli/template_data/harmonyos/template/Makefile +106 -0
- biucingcli/template_data/harmonyos/template/README.md +152 -0
- biucingcli/template_data/harmonyos/template/build-profile.json5 +36 -0
- biucingcli/template_data/harmonyos/template/code-linter.json5 +12 -0
- biucingcli/template_data/harmonyos/template/docs/release-signing.local.properties.example +14 -0
- biucingcli/template_data/harmonyos/template/entry/build-profile.json5 +9 -0
- biucingcli/template_data/harmonyos/template/entry/hvigorfile.ts +6 -0
- biucingcli/template_data/harmonyos/template/entry/oh-package.json5 +9 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/ets/core/config/AppConfig.ets +10 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/ets/core/designsystem/Tokens.ets +28 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/ets/entryability/EntryAbility.ets +29 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/ets/pages/Index.ets +47 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/ets/pages/Settings.ets +96 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/module.json5 +34 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/element/color.json +24 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/element/string.json +12 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/media/app_icon.svg +5 -0
- biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/profile/main_pages.json +6 -0
- biucingcli/template_data/harmonyos/template/entry/src/test/List.test.ets +11 -0
- biucingcli/template_data/harmonyos/template/hvigor/hvigor-config.json5 +8 -0
- biucingcli/template_data/harmonyos/template/hvigorfile.ts +6 -0
- biucingcli/template_data/harmonyos/template/oh-package-lock.json5 +19 -0
- biucingcli/template_data/harmonyos/template/oh-package.json5 +13 -0
- biucingcli/template_data/harmonyos/template/scripts/artifact-info +31 -0
- biucingcli/template_data/harmonyos/template/scripts/bootstrap +38 -0
- biucingcli/template_data/harmonyos/template/scripts/doctor +147 -0
- biucingcli/template_data/harmonyos/template/scripts/lint +105 -0
- biucingcli/template_data/harmonyos/template/scripts/release-build +199 -0
- biucingcli/template_data/harmonyos/template/scripts/release-preflight +109 -0
- biucingcli/template_data/harmonyos/template/scripts/test +28 -0
- biucingcli/template_data/harmonyos/template/scripts/verify-release-artifact +173 -0
- biucingcli/template_data/harmonyos/template/scripts/verify-supply-chain +70 -0
- biucingcli/template_data/harmonyos/template.json +134 -0
- biucingcli/template_data/microservice/template/.air.toml +11 -0
- biucingcli/template_data/microservice/template/.dockerignore +5 -0
- biucingcli/template_data/microservice/template/.gitignore +4 -0
- biucingcli/template_data/microservice/template/.mise.toml +3 -0
- biucingcli/template_data/microservice/template/Brewfile +7 -0
- biucingcli/template_data/microservice/template/Dockerfile +44 -0
- biucingcli/template_data/microservice/template/Dockerfile.dev +50 -0
- biucingcli/template_data/microservice/template/Makefile +145 -0
- biucingcli/template_data/microservice/template/README.md +191 -0
- biucingcli/template_data/microservice/template/api/buf.gen.yaml +11 -0
- biucingcli/template_data/microservice/template/api/buf.yaml +11 -0
- biucingcli/template_data/microservice/template/api/proto/service/v1/service.proto +18 -0
- biucingcli/template_data/microservice/template/cmd/server/main.go +81 -0
- biucingcli/template_data/microservice/template/compose.dev.yaml +49 -0
- biucingcli/template_data/microservice/template/configs/config.yaml +18 -0
- biucingcli/template_data/microservice/template/deploy/compose.yaml +35 -0
- biucingcli/template_data/microservice/template/deploy/otel-collector.yaml +15 -0
- biucingcli/template_data/microservice/template/go.mod +53 -0
- biucingcli/template_data/microservice/template/go.sum +138 -0
- biucingcli/template_data/microservice/template/internal/config/config.go +112 -0
- biucingcli/template_data/microservice/template/internal/config/config_test.go +92 -0
- biucingcli/template_data/microservice/template/internal/handler/health.go +25 -0
- biucingcli/template_data/microservice/template/internal/handler/ping.go +25 -0
- biucingcli/template_data/microservice/template/internal/model/health.go +8 -0
- biucingcli/template_data/microservice/template/internal/model/ping.go +7 -0
- biucingcli/template_data/microservice/template/internal/repository/.gitkeep +1 -0
- biucingcli/template_data/microservice/template/internal/router/router.go +26 -0
- biucingcli/template_data/microservice/template/internal/runtime/server.go +116 -0
- biucingcli/template_data/microservice/template/internal/runtime/server_test.go +161 -0
- biucingcli/template_data/microservice/template/internal/service/health.go +26 -0
- biucingcli/template_data/microservice/template/internal/service/ping.go +23 -0
- biucingcli/template_data/microservice/template/internal/telemetry/telemetry.go +56 -0
- biucingcli/template_data/microservice/template/internal/transport/grpc.go +51 -0
- biucingcli/template_data/microservice/template/internal/transport/ping.go +28 -0
- biucingcli/template_data/microservice/template/scripts/bootstrap +29 -0
- biucingcli/template_data/microservice/template/scripts/doctor +115 -0
- biucingcli/template_data/microservice/template/tests/server_test.go +153 -0
- biucingcli/template_data/microservice/template.json +114 -0
- biucingcli/template_data/web-service/template/.air.toml +11 -0
- biucingcli/template_data/web-service/template/.dockerignore +5 -0
- biucingcli/template_data/web-service/template/.gitignore +5 -0
- biucingcli/template_data/web-service/template/.mise.toml +2 -0
- biucingcli/template_data/web-service/template/Brewfile +5 -0
- biucingcli/template_data/web-service/template/Dockerfile +41 -0
- biucingcli/template_data/web-service/template/Dockerfile.dev +45 -0
- biucingcli/template_data/web-service/template/Makefile +113 -0
- biucingcli/template_data/web-service/template/README.md +164 -0
- biucingcli/template_data/web-service/template/cmd/server/main.go +50 -0
- biucingcli/template_data/web-service/template/compose.dev.yaml +28 -0
- biucingcli/template_data/web-service/template/compose.yaml +14 -0
- biucingcli/template_data/web-service/template/configs/config.yaml +10 -0
- biucingcli/template_data/web-service/template/go.mod +36 -0
- biucingcli/template_data/web-service/template/go.sum +89 -0
- biucingcli/template_data/web-service/template/internal/config/config.go +84 -0
- biucingcli/template_data/web-service/template/internal/config/config_test.go +88 -0
- biucingcli/template_data/web-service/template/internal/handler/health.go +25 -0
- biucingcli/template_data/web-service/template/internal/handler/ping.go +25 -0
- biucingcli/template_data/web-service/template/internal/handler/user.go +40 -0
- biucingcli/template_data/web-service/template/internal/model/health.go +6 -0
- biucingcli/template_data/web-service/template/internal/model/ping.go +7 -0
- biucingcli/template_data/web-service/template/internal/model/user.go +7 -0
- biucingcli/template_data/web-service/template/internal/repository/.gitkeep +1 -0
- biucingcli/template_data/web-service/template/internal/repository/user.go +37 -0
- biucingcli/template_data/web-service/template/internal/router/router.go +28 -0
- biucingcli/template_data/web-service/template/internal/runtime/server.go +76 -0
- biucingcli/template_data/web-service/template/internal/runtime/server_test.go +139 -0
- biucingcli/template_data/web-service/template/internal/service/health.go +22 -0
- biucingcli/template_data/web-service/template/internal/service/ping.go +23 -0
- biucingcli/template_data/web-service/template/internal/service/user.go +27 -0
- biucingcli/template_data/web-service/template/scripts/bootstrap +23 -0
- biucingcli/template_data/web-service/template/scripts/doctor +83 -0
- biucingcli/template_data/web-service/template/tests/server_test.go +160 -0
- biucingcli/template_data/web-service/template.json +88 -0
- biucingcli/template_data/worker/template/.dockerignore +3 -0
- biucingcli/template_data/worker/template/.gitignore +2 -0
- biucingcli/template_data/worker/template/.mise.toml +2 -0
- biucingcli/template_data/worker/template/Brewfile +1 -0
- biucingcli/template_data/worker/template/Dockerfile +19 -0
- biucingcli/template_data/worker/template/Dockerfile.dev +9 -0
- biucingcli/template_data/worker/template/Makefile +105 -0
- biucingcli/template_data/worker/template/README.md +164 -0
- biucingcli/template_data/worker/template/cmd/worker/main.go +41 -0
- biucingcli/template_data/worker/template/compose.dev.yaml +29 -0
- biucingcli/template_data/worker/template/configs/config.json +11 -0
- biucingcli/template_data/worker/template/go.mod +3 -0
- biucingcli/template_data/worker/template/go.sum +1 -0
- biucingcli/template_data/worker/template/internal/config/config.go +108 -0
- biucingcli/template_data/worker/template/internal/config/config_test.go +86 -0
- biucingcli/template_data/worker/template/internal/runtime/runner.go +199 -0
- biucingcli/template_data/worker/template/internal/runtime/runner_test.go +215 -0
- biucingcli/template_data/worker/template/internal/task/heartbeat.go +19 -0
- biucingcli/template_data/worker/template/scripts/bootstrap +6 -0
- biucingcli/template_data/worker/template/scripts/doctor +41 -0
- biucingcli/template_data/worker/template/tests/worker_test.go +44 -0
- biucingcli/template_data/worker/template.json +100 -0
- biucingcli/templates.py +902 -0
- biucingcli-0.9.1.dist-info/METADATA +204 -0
- biucingcli-0.9.1.dist-info/RECORD +269 -0
- biucingcli-0.9.1.dist-info/WHEEL +5 -0
- biucingcli-0.9.1.dist-info/entry_points.txt +2 -0
- biucingcli-0.9.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
HVIGOR_BIN="${HVIGOR:-hvigorw}"
|
|
5
|
+
MODULE_NAME="{{HARMONY_MODULE_NAME}}"
|
|
6
|
+
BUILD_PROFILE="build-profile.json5"
|
|
7
|
+
BACKUP_DIR=".biucing/release"
|
|
8
|
+
BACKUP_PROFILE="${BACKUP_DIR}/build-profile.json5.backup"
|
|
9
|
+
GENERATED_PROFILE="${BACKUP_DIR}/build-profile.json5.generated"
|
|
10
|
+
RESTORE_PROFILE="${BACKUP_DIR}/build-profile.json5.restore"
|
|
11
|
+
BUILD_MARKER="${BACKUP_DIR}/release-build.started"
|
|
12
|
+
|
|
13
|
+
if [[ ! -f "local.properties" ]]; then
|
|
14
|
+
cat >&2 <<'EOF'
|
|
15
|
+
local.properties is missing.
|
|
16
|
+
|
|
17
|
+
Copy docs/release-signing.local.properties.example to local.properties and fill in
|
|
18
|
+
your HarmonyOS signing material before running make release.
|
|
19
|
+
EOF
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
./scripts/verify-supply-chain
|
|
24
|
+
./scripts/release-preflight
|
|
25
|
+
|
|
26
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || \
|
|
27
|
+
! git ls-files --error-unmatch "$BUILD_PROFILE" >/dev/null 2>&1; then
|
|
28
|
+
echo "$BUILD_PROFILE must be tracked in a Git repository before a signed release." >&2
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if ! git diff --quiet -- "$BUILD_PROFILE" || ! git diff --cached --quiet -- "$BUILD_PROFILE"; then
|
|
33
|
+
echo "$BUILD_PROFILE has staged or unstaged changes." >&2
|
|
34
|
+
echo "Commit or stash those changes before running a signed release." >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if ORIGINAL_MODE="$(stat -f '%Lp' "$BUILD_PROFILE" 2>/dev/null)"; then
|
|
39
|
+
:
|
|
40
|
+
else
|
|
41
|
+
ORIGINAL_MODE="$(stat -c '%a' "$BUILD_PROFILE")"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
umask 077
|
|
45
|
+
mkdir -p "$BACKUP_DIR"
|
|
46
|
+
cp -p "$BUILD_PROFILE" "$BACKUP_PROFILE"
|
|
47
|
+
chmod 600 "$BACKUP_PROFILE"
|
|
48
|
+
|
|
49
|
+
restore_build_profile() {
|
|
50
|
+
local original_status=$?
|
|
51
|
+
local restore_status=0
|
|
52
|
+
|
|
53
|
+
trap - EXIT HUP INT TERM
|
|
54
|
+
rm -f "$GENERATED_PROFILE" "$RESTORE_PROFILE" "$BUILD_MARKER"
|
|
55
|
+
|
|
56
|
+
if [[ -f "$BACKUP_PROFILE" ]]; then
|
|
57
|
+
if cp -p "$BACKUP_PROFILE" "$RESTORE_PROFILE" && \
|
|
58
|
+
mv -f "$RESTORE_PROFILE" "$BUILD_PROFILE" && chmod "$ORIGINAL_MODE" "$BUILD_PROFILE"; then
|
|
59
|
+
if cmp -s "$BACKUP_PROFILE" "$BUILD_PROFILE"; then
|
|
60
|
+
rm -f "$BACKUP_PROFILE"
|
|
61
|
+
rmdir "$BACKUP_DIR" 2>/dev/null || true
|
|
62
|
+
else
|
|
63
|
+
echo "Failed to verify restoration of $BUILD_PROFILE; backup retained at $BACKUP_PROFILE." >&2
|
|
64
|
+
restore_status=1
|
|
65
|
+
fi
|
|
66
|
+
else
|
|
67
|
+
echo "Failed to restore $BUILD_PROFILE; backup retained at $BACKUP_PROFILE." >&2
|
|
68
|
+
restore_status=1
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
if [[ "$restore_status" -ne 0 ]]; then
|
|
73
|
+
exit "$restore_status"
|
|
74
|
+
fi
|
|
75
|
+
exit "$original_status"
|
|
76
|
+
}
|
|
77
|
+
trap restore_build_profile EXIT
|
|
78
|
+
trap 'exit 129' HUP
|
|
79
|
+
trap 'exit 130' INT
|
|
80
|
+
trap 'exit 143' TERM
|
|
81
|
+
|
|
82
|
+
BUILD_PROFILE_PATH="$BUILD_PROFILE" GENERATED_PROFILE_PATH="$GENERATED_PROFILE" node <<'NODE'
|
|
83
|
+
const fs = require('fs');
|
|
84
|
+
const path = require('path');
|
|
85
|
+
|
|
86
|
+
const localPropertiesPath = 'local.properties';
|
|
87
|
+
const buildProfilePath = process.env.BUILD_PROFILE_PATH;
|
|
88
|
+
const generatedProfilePath = process.env.GENERATED_PROFILE_PATH;
|
|
89
|
+
const requiredKeys = [
|
|
90
|
+
'biucing.harmony.signing.certpath',
|
|
91
|
+
'biucing.harmony.signing.profile',
|
|
92
|
+
'biucing.harmony.signing.storeFile',
|
|
93
|
+
'biucing.harmony.signing.storePassword',
|
|
94
|
+
'biucing.harmony.signing.keyAlias',
|
|
95
|
+
'biucing.harmony.signing.keyPassword'
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
function parseProperties(raw) {
|
|
99
|
+
const values = {};
|
|
100
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
101
|
+
const trimmed = line.trim();
|
|
102
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const separator = trimmed.indexOf('=');
|
|
106
|
+
if (separator < 0) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const key = trimmed.slice(0, separator).trim();
|
|
110
|
+
const value = trimmed.slice(separator + 1).trim();
|
|
111
|
+
values[key] = value;
|
|
112
|
+
}
|
|
113
|
+
return values;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const properties = parseProperties(fs.readFileSync(localPropertiesPath, 'utf8'));
|
|
117
|
+
const missing = requiredKeys.filter((key) => !properties[key]);
|
|
118
|
+
if (missing.length > 0) {
|
|
119
|
+
console.error(`Missing signing key(s) in ${localPropertiesPath}:`);
|
|
120
|
+
for (const key of missing) {
|
|
121
|
+
console.error(` - ${key}`);
|
|
122
|
+
}
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
for (const key of [
|
|
127
|
+
'biucing.harmony.signing.certpath',
|
|
128
|
+
'biucing.harmony.signing.profile',
|
|
129
|
+
'biucing.harmony.signing.storeFile'
|
|
130
|
+
]) {
|
|
131
|
+
const value = properties[key];
|
|
132
|
+
const resolved = path.isAbsolute(value) ? value : path.resolve(value);
|
|
133
|
+
if (!fs.existsSync(resolved)) {
|
|
134
|
+
console.error(`Signing file for ${key} does not exist: ${value}`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const buildProfile = JSON.parse(fs.readFileSync(buildProfilePath, 'utf8'));
|
|
140
|
+
const material = {
|
|
141
|
+
certpath: properties['biucing.harmony.signing.certpath'],
|
|
142
|
+
profile: properties['biucing.harmony.signing.profile'],
|
|
143
|
+
storeFile: properties['biucing.harmony.signing.storeFile'],
|
|
144
|
+
storePassword: properties['biucing.harmony.signing.storePassword'],
|
|
145
|
+
keyAlias: properties['biucing.harmony.signing.keyAlias'],
|
|
146
|
+
keyPassword: properties['biucing.harmony.signing.keyPassword'],
|
|
147
|
+
signAlg: properties['biucing.harmony.signing.signAlg'] || 'SHA256withECDSA'
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
buildProfile.app.signingConfigs = [
|
|
151
|
+
{
|
|
152
|
+
name: 'release',
|
|
153
|
+
type: 'HarmonyOS',
|
|
154
|
+
material
|
|
155
|
+
}
|
|
156
|
+
];
|
|
157
|
+
for (const product of buildProfile.app.products || []) {
|
|
158
|
+
product.signingConfig = 'release';
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
fs.writeFileSync(generatedProfilePath, `${JSON.stringify(buildProfile, null, 2)}\n`, { mode: 0o600 });
|
|
162
|
+
console.log('Injected release signing config from local.properties.');
|
|
163
|
+
NODE
|
|
164
|
+
|
|
165
|
+
mv -f "$GENERATED_PROFILE" "$BUILD_PROFILE"
|
|
166
|
+
|
|
167
|
+
touch "$BUILD_MARKER"
|
|
168
|
+
"$HVIGOR_BIN" assembleHap --mode module -p "module=${MODULE_NAME}" -p buildMode=release
|
|
169
|
+
release_artifact="$(MODULE_BUILD_ROOT="${MODULE_NAME}/build" BUILD_MARKER_PATH="$BUILD_MARKER" node <<'NODE'
|
|
170
|
+
const fs = require('fs');
|
|
171
|
+
const path = require('path');
|
|
172
|
+
const markerTime = fs.statSync(process.env.BUILD_MARKER_PATH).mtimeMs;
|
|
173
|
+
const candidates = [];
|
|
174
|
+
|
|
175
|
+
function visit(directory) {
|
|
176
|
+
if (!fs.existsSync(directory)) return;
|
|
177
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
178
|
+
const candidate = path.join(directory, entry.name);
|
|
179
|
+
if (entry.isDirectory()) {
|
|
180
|
+
visit(candidate);
|
|
181
|
+
} else if (entry.isFile() && candidate.endsWith('.hap')) {
|
|
182
|
+
const modified = fs.statSync(candidate).mtimeMs;
|
|
183
|
+
if (modified > markerTime) candidates.push({ candidate, modified });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
visit(process.env.MODULE_BUILD_ROOT);
|
|
189
|
+
candidates.sort((left, right) => right.modified - left.modified);
|
|
190
|
+
if (candidates.length > 0) process.stdout.write(candidates[0].candidate);
|
|
191
|
+
NODE
|
|
192
|
+
)"
|
|
193
|
+
if [[ -z "$release_artifact" ]]; then
|
|
194
|
+
echo "Release build did not produce a new HAP artifact." >&2
|
|
195
|
+
exit 1
|
|
196
|
+
fi
|
|
197
|
+
./scripts/verify-release-artifact "$release_artifact"
|
|
198
|
+
|
|
199
|
+
echo "Release build finished. Restoring build-profile.json5."
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "HarmonyOS release signing preflight"
|
|
5
|
+
|
|
6
|
+
node <<'NODE'
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const buildProfilePath = 'build-profile.json5';
|
|
10
|
+
let buildProfile;
|
|
11
|
+
try {
|
|
12
|
+
buildProfile = JSON.parse(fs.readFileSync(buildProfilePath, 'utf8'));
|
|
13
|
+
} catch (_error) {
|
|
14
|
+
console.error(`${buildProfilePath} is missing or is not valid JSON.`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const signingConfigs = buildProfile?.app?.signingConfigs;
|
|
19
|
+
const containsPasswordField = (value) => {
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
return value.some(containsPasswordField);
|
|
22
|
+
}
|
|
23
|
+
if (!value || typeof value !== 'object') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return Object.entries(value).some(([key, child]) => {
|
|
28
|
+
if ((key === 'storePassword' || key === 'keyPassword') && String(child || '').length > 0) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return containsPasswordField(child);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (!Array.isArray(signingConfigs) || signingConfigs.length > 0 || containsPasswordField(buildProfile)) {
|
|
36
|
+
console.error(`${buildProfilePath} contains signing material.`);
|
|
37
|
+
console.error('Restore the committed unsigned build profile before running a release.');
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
NODE
|
|
41
|
+
|
|
42
|
+
if [[ ! -f "local.properties" ]]; then
|
|
43
|
+
cat >&2 <<'EOF'
|
|
44
|
+
local.properties is missing.
|
|
45
|
+
|
|
46
|
+
Copy docs/release-signing.local.properties.example to local.properties and fill in
|
|
47
|
+
your HarmonyOS signing material before running make release.
|
|
48
|
+
EOF
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
node <<'NODE'
|
|
53
|
+
const fs = require('fs');
|
|
54
|
+
const path = require('path');
|
|
55
|
+
|
|
56
|
+
const localPropertiesPath = 'local.properties';
|
|
57
|
+
const requiredKeys = [
|
|
58
|
+
'biucing.harmony.signing.certpath',
|
|
59
|
+
'biucing.harmony.signing.profile',
|
|
60
|
+
'biucing.harmony.signing.storeFile',
|
|
61
|
+
'biucing.harmony.signing.storePassword',
|
|
62
|
+
'biucing.harmony.signing.keyAlias',
|
|
63
|
+
'biucing.harmony.signing.keyPassword'
|
|
64
|
+
];
|
|
65
|
+
const fileKeys = [
|
|
66
|
+
'biucing.harmony.signing.certpath',
|
|
67
|
+
'biucing.harmony.signing.profile',
|
|
68
|
+
'biucing.harmony.signing.storeFile'
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
function parseProperties(raw) {
|
|
72
|
+
const values = {};
|
|
73
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
74
|
+
const trimmed = line.trim();
|
|
75
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const separator = trimmed.indexOf('=');
|
|
79
|
+
if (separator < 0) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const key = trimmed.slice(0, separator).trim();
|
|
83
|
+
const value = trimmed.slice(separator + 1).trim();
|
|
84
|
+
values[key] = value;
|
|
85
|
+
}
|
|
86
|
+
return values;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const properties = parseProperties(fs.readFileSync(localPropertiesPath, 'utf8'));
|
|
90
|
+
const missing = requiredKeys.filter((key) => !properties[key]);
|
|
91
|
+
if (missing.length > 0) {
|
|
92
|
+
console.error(`Missing signing key(s) in ${localPropertiesPath}:`);
|
|
93
|
+
for (const key of missing) {
|
|
94
|
+
console.error(` - ${key}`);
|
|
95
|
+
}
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const key of fileKeys) {
|
|
100
|
+
const value = properties[key];
|
|
101
|
+
const resolved = path.isAbsolute(value) ? value : path.resolve(value);
|
|
102
|
+
if (!fs.existsSync(resolved)) {
|
|
103
|
+
console.error(`Signing file for ${key} does not exist: ${value}`);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('Release signing material is present and file paths resolve.');
|
|
109
|
+
NODE
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
HVIGOR_BIN="${HVIGOR:-hvigorw}"
|
|
5
|
+
MODULE_NAME="{{HARMONY_MODULE_NAME}}"
|
|
6
|
+
|
|
7
|
+
echo "Running HarmonyOS ArkTS unit tests with hvigor..."
|
|
8
|
+
|
|
9
|
+
if [[ ! -f "entry/src/test/List.test.ets" ]]; then
|
|
10
|
+
cat >&2 <<'EOF'
|
|
11
|
+
entry/src/test/List.test.ets is missing.
|
|
12
|
+
|
|
13
|
+
Keep at least one Hypium test suite in the generated project before treating
|
|
14
|
+
the project as release-ready.
|
|
15
|
+
EOF
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
if [[ ! -d "oh_modules/@ohos/hypium" && ! -d "entry/oh_modules/@ohos/hypium" ]]; then
|
|
20
|
+
cat >&2 <<'EOF'
|
|
21
|
+
@ohos/hypium is not installed.
|
|
22
|
+
|
|
23
|
+
Run make bootstrap before make test so ohpm can install test dependencies.
|
|
24
|
+
EOF
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
"$HVIGOR_BIN" test --mode module -p "module=${MODULE_NAME}"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
EXPECTED_BUNDLE_NAME="{{BUNDLE_NAME}}"
|
|
5
|
+
properties_path="local.properties"
|
|
6
|
+
keytool_bin="${KEYTOOL:-keytool}"
|
|
7
|
+
|
|
8
|
+
property_value() {
|
|
9
|
+
local key="$1"
|
|
10
|
+
awk -F= -v expected="$key" '
|
|
11
|
+
$0 !~ /^[[:space:]]*#/ && $1 ~ "^[[:space:]]*" expected "[[:space:]]*$" {
|
|
12
|
+
sub(/^[^=]*=/, ""); sub(/^[[:space:]]+/, ""); sub(/[[:space:]]+$/, ""); print; exit
|
|
13
|
+
}
|
|
14
|
+
' "$properties_path"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fingerprint_from_certificate() {
|
|
18
|
+
LC_ALL=C "$keytool_bin" -printcert -file "$1" 2>/dev/null \
|
|
19
|
+
| sed -nE 's/.*SHA-?256:[[:space:]]*([0-9A-Fa-f:]+).*/\1/p' \
|
|
20
|
+
| head -n 1 \
|
|
21
|
+
| tr '[:lower:]' '[:upper:]' \
|
|
22
|
+
| tr -d ':[:space:]'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
find_sign_tool() {
|
|
26
|
+
if [[ -n "${HAP_SIGN_TOOL:-}" ]]; then
|
|
27
|
+
printf '%s' "$HAP_SIGN_TOOL"
|
|
28
|
+
return
|
|
29
|
+
fi
|
|
30
|
+
local sdk_root="${DEVECO_SDK_HOME:-${HOS_SDK_HOME:-${OHOS_SDK_HOME:-}}}"
|
|
31
|
+
local candidate
|
|
32
|
+
for candidate in \
|
|
33
|
+
"$sdk_root/default/openharmony/toolchains/lib/hap-sign-tool.jar" \
|
|
34
|
+
"/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony/toolchains/lib/hap-sign-tool.jar"; do
|
|
35
|
+
if [[ -f "$candidate" ]]; then
|
|
36
|
+
printf '%s' "$candidate"
|
|
37
|
+
return
|
|
38
|
+
fi
|
|
39
|
+
done
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
artifact_path="${1:-}"
|
|
43
|
+
if [[ -z "$artifact_path" ]]; then
|
|
44
|
+
artifact_path="$(find "{{HARMONY_MODULE_NAME}}/build" -type f -name '*.hap' -print 2>/dev/null | sort | tail -n 1)"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "HarmonyOS release artifact signature verification"
|
|
48
|
+
|
|
49
|
+
if [[ -z "$artifact_path" || ! -s "$artifact_path" ]]; then
|
|
50
|
+
echo "Signed HAP artifact is missing or empty." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
if ! unzip -tqq "$artifact_path"; then
|
|
54
|
+
echo "HAP archive validation failed: $artifact_path" >&2
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
if [[ ! -f "$properties_path" ]]; then
|
|
58
|
+
echo "$properties_path is required to verify the expected signer and profile." >&2
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
if ! command -v "$keytool_bin" >/dev/null 2>&1 && [[ ! -x "$keytool_bin" ]]; then
|
|
62
|
+
echo "keytool is required to compare signing certificate fingerprints." >&2
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
cert_path="$(property_value biucing.harmony.signing.certpath)"
|
|
67
|
+
profile_path="$(property_value biucing.harmony.signing.profile)"
|
|
68
|
+
for variable_name in cert_path profile_path; do
|
|
69
|
+
value="${!variable_name:-}"
|
|
70
|
+
if [[ -z "$value" ]]; then
|
|
71
|
+
echo "Missing signing property for $variable_name." >&2
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
if [[ "$value" != /* ]]; then
|
|
75
|
+
printf -v "$variable_name" '%s' "$PWD/$value"
|
|
76
|
+
fi
|
|
77
|
+
if [[ ! -f "${!variable_name}" ]]; then
|
|
78
|
+
echo "Configured signing input does not exist: ${!variable_name}" >&2
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
sign_tool="$(find_sign_tool)"
|
|
84
|
+
if [[ -z "$sign_tool" || ( ! -f "$sign_tool" && ! -x "$sign_tool" ) ]]; then
|
|
85
|
+
echo "hap-sign-tool is unavailable. Set HAP_SIGN_TOOL or DEVECO_SDK_HOME." >&2
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
verification_dir="$(mktemp -d "${TMPDIR:-/tmp}/biucing-hap-verify.XXXXXX")"
|
|
90
|
+
chmod 700 "$verification_dir"
|
|
91
|
+
out_certchain="$verification_dir/certificate-chain.cer"
|
|
92
|
+
out_profile="$verification_dir/profile.p7b"
|
|
93
|
+
profile_result="$verification_dir/profile-verification.json"
|
|
94
|
+
cleanup() {
|
|
95
|
+
rm -f "$out_certchain" "$out_profile" "$profile_result"
|
|
96
|
+
rmdir "$verification_dir" 2>/dev/null || true
|
|
97
|
+
}
|
|
98
|
+
trap cleanup EXIT HUP INT TERM
|
|
99
|
+
|
|
100
|
+
if [[ "$sign_tool" == *.jar ]]; then
|
|
101
|
+
java -jar "$sign_tool" verify-app \
|
|
102
|
+
-inFile "$artifact_path" \
|
|
103
|
+
-outCertChain "$out_certchain" \
|
|
104
|
+
-outProfile "$out_profile" \
|
|
105
|
+
-inForm zip >/dev/null
|
|
106
|
+
else
|
|
107
|
+
"$sign_tool" verify-app \
|
|
108
|
+
-inFile "$artifact_path" \
|
|
109
|
+
-outCertChain "$out_certchain" \
|
|
110
|
+
-outProfile "$out_profile" \
|
|
111
|
+
-inForm zip >/dev/null
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
if [[ ! -s "$out_certchain" || ! -s "$out_profile" ]]; then
|
|
115
|
+
echo "hap-sign-tool did not export a signer certificate chain and profile." >&2
|
|
116
|
+
exit 1
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
expected_fingerprint="$(fingerprint_from_certificate "$cert_path")"
|
|
120
|
+
actual_fingerprint="$(fingerprint_from_certificate "$out_certchain")"
|
|
121
|
+
if [[ -z "$expected_fingerprint" || -z "$actual_fingerprint" ]]; then
|
|
122
|
+
echo "Unable to read the configured or embedded signer certificate fingerprint." >&2
|
|
123
|
+
exit 1
|
|
124
|
+
fi
|
|
125
|
+
if [[ "$actual_fingerprint" != "$expected_fingerprint" ]]; then
|
|
126
|
+
echo "HAP signer certificate does not match the configured release certificate." >&2
|
|
127
|
+
echo "expected: $expected_fingerprint" >&2
|
|
128
|
+
echo "actual: $actual_fingerprint" >&2
|
|
129
|
+
exit 1
|
|
130
|
+
fi
|
|
131
|
+
if ! cmp -s "$profile_path" "$out_profile"; then
|
|
132
|
+
echo "HAP embedded signing profile does not match the configured release profile." >&2
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
if [[ "$sign_tool" == *.jar ]]; then
|
|
137
|
+
java -jar "$sign_tool" verify-profile -inFile "$out_profile" -outFile "$profile_result" >/dev/null
|
|
138
|
+
else
|
|
139
|
+
"$sign_tool" verify-profile -inFile "$out_profile" -outFile "$profile_result" >/dev/null
|
|
140
|
+
fi
|
|
141
|
+
if [[ ! -s "$profile_result" ]]; then
|
|
142
|
+
echo "hap-sign-tool did not produce a verified profile result." >&2
|
|
143
|
+
exit 1
|
|
144
|
+
fi
|
|
145
|
+
EXPECTED_BUNDLE_NAME="$EXPECTED_BUNDLE_NAME" PROFILE_RESULT="$profile_result" node <<'NODE'
|
|
146
|
+
const fs = require('fs');
|
|
147
|
+
const result = JSON.parse(fs.readFileSync(process.env.PROFILE_RESULT, 'utf8'));
|
|
148
|
+
const found = [];
|
|
149
|
+
function visit(value) {
|
|
150
|
+
if (Array.isArray(value)) {
|
|
151
|
+
value.forEach(visit);
|
|
152
|
+
} else if (typeof value === 'string' && value.trim().startsWith('{')) {
|
|
153
|
+
try { visit(JSON.parse(value)); } catch (_error) { /* not an embedded JSON object */ }
|
|
154
|
+
} else if (value && typeof value === 'object') {
|
|
155
|
+
for (const [key, child] of Object.entries(value)) {
|
|
156
|
+
if (key.toLowerCase().replace(/[-_.]/g, '') === 'bundlename') {
|
|
157
|
+
found.push(String(child));
|
|
158
|
+
}
|
|
159
|
+
visit(child);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
visit(result);
|
|
164
|
+
if (!found.includes(process.env.EXPECTED_BUNDLE_NAME)) {
|
|
165
|
+
console.error('Verified HAP profile bundle identity does not match the template release bundle.');
|
|
166
|
+
console.error(`expected: ${process.env.EXPECTED_BUNDLE_NAME}`);
|
|
167
|
+
console.error(`actual: ${found.length > 0 ? found.join(', ') : '<missing>'}`);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
NODE
|
|
171
|
+
|
|
172
|
+
echo "HAP signature is valid; signer and embedded profile match local release inputs."
|
|
173
|
+
echo "Bundle: $EXPECTED_BUNDLE_NAME"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "HarmonyOS ohpm supply-chain verification"
|
|
5
|
+
|
|
6
|
+
node <<'NODE'
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
|
|
9
|
+
const manifestPath = 'oh-package.json5';
|
|
10
|
+
const lockPath = 'oh-package-lock.json5';
|
|
11
|
+
const allowedRegistryPrefix = 'https://ohpm.openharmony.cn/ohpm/';
|
|
12
|
+
const failures = [];
|
|
13
|
+
|
|
14
|
+
function load(path) {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(fs.readFileSync(path, 'utf8'));
|
|
17
|
+
} catch (_error) {
|
|
18
|
+
failures.push(`${path} is missing or is not valid JSON.`);
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const manifest = load(manifestPath);
|
|
24
|
+
const lock = load(lockPath);
|
|
25
|
+
const declared = { ...(manifest.dependencies || {}), ...(manifest.devDependencies || {}) };
|
|
26
|
+
const specifiers = lock.specifiers || {};
|
|
27
|
+
const packages = lock.packages || {};
|
|
28
|
+
|
|
29
|
+
if (lock.lockfileVersion !== 3) {
|
|
30
|
+
failures.push(`${lockPath} must use lockfileVersion 3.`);
|
|
31
|
+
}
|
|
32
|
+
if (lock?.meta?.stableOrder !== true) {
|
|
33
|
+
failures.push(`${lockPath} must enable meta.stableOrder.`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
for (const [name, version] of Object.entries(declared)) {
|
|
37
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(String(version))) {
|
|
38
|
+
failures.push(`${name} must use an exact version; found ${version}.`);
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const key = `${name}@${version}`;
|
|
42
|
+
if (specifiers[key] !== key) {
|
|
43
|
+
failures.push(`${key} is not pinned by lockfile specifiers.`);
|
|
44
|
+
}
|
|
45
|
+
if (!packages[key]) {
|
|
46
|
+
failures.push(`${key} is missing from lockfile packages.`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
for (const [key, pkg] of Object.entries(packages)) {
|
|
51
|
+
if (!/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(String(pkg.integrity || ''))) {
|
|
52
|
+
failures.push(`${key} is missing a valid sha512 integrity value.`);
|
|
53
|
+
}
|
|
54
|
+
if (!String(pkg.resolved || '').startsWith(allowedRegistryPrefix)) {
|
|
55
|
+
failures.push(`${key} resolves outside the approved ohpm registry.`);
|
|
56
|
+
}
|
|
57
|
+
if (pkg.registryType !== 'ohpm') {
|
|
58
|
+
failures.push(`${key} must use registryType ohpm.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (failures.length > 0) {
|
|
63
|
+
for (const failure of failures) {
|
|
64
|
+
console.error(`[fail] ${failure}`);
|
|
65
|
+
}
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(`Pinned ${Object.keys(packages).length} package(s) with registry and integrity checks.`);
|
|
70
|
+
NODE
|