docs(sdk): 添加 React Native SDK 文档和 Android/HarmonyOS 发版脚本
- 新增 XuqmGroup React Native SDK 使用文档,包含安装、初始化、HTTP客户端、IM模块、推送模块、版本管理等功能说明 - 添加 Android Gradle 发版任务脚本,支持构建发布 APK 并上传到更新服务 - 添加 HarmonyOS hvigorw 发版任务脚本,支持 HAP 包构建和上传功能 - 实现多平台版本检查、自动重连、灰度发布等发版流程自动化 - 集成商店提交、定时发布、Webhook 回调等发布后处理功能
这个提交包含在:
父节点
2352b46c6b
当前提交
eaf1c00d20
@ -34,14 +34,19 @@ platform :ios do
|
||||
server_url = ENV.fetch("XUQM_SERVER_URL")
|
||||
app_key = ENV.fetch("XUQM_APP_KEY")
|
||||
api_token = ENV.fetch("XUQM_API_TOKEN")
|
||||
tenant_url = ENV.fetch("XUQM_TENANT_URL", "").strip
|
||||
scheme = ENV.fetch("XUQM_SCHEME")
|
||||
workspace = ENV.fetch("XUQM_WORKSPACE")
|
||||
bundle_id = ENV.fetch("XUQM_BUNDLE_ID", "")
|
||||
store_targets = ENV.fetch("XUQM_STORE_TARGETS", "")
|
||||
auto_publish = ENV.fetch("XUQM_AUTO_PUBLISH_AFTER_REVIEW", "false") == "true"
|
||||
publish_immediately = ENV.fetch("XUQM_PUBLISH_IMMEDIATELY", "false") == "true"
|
||||
webhook_url = ENV.fetch("XUQM_WEBHOOK_URL", "")
|
||||
scheduled_at = ENV.fetch("XUQM_SCHEDULED_PUBLISH_AT", "")
|
||||
tenant_cfg = xuqm_fetch_sdk_config(tenant_url, app_key, "IOS")
|
||||
store_targets = ENV.fetch("XUQM_STORE_TARGETS", tenant_cfg.fetch("updateDefaultStoreTargets", "APP_STORE"))
|
||||
auto_publish = ENV.fetch("XUQM_AUTO_PUBLISH_AFTER_REVIEW", tenant_cfg.fetch("updateDefaultAutoPublishAfterReview", "false")) == "true"
|
||||
publish_immediately = ENV.fetch("XUQM_PUBLISH_IMMEDIATELY", tenant_cfg.fetch("updateDefaultPublishImmediately", "false")) == "true"
|
||||
webhook_url = ENV.fetch("XUQM_WEBHOOK_URL", tenant_cfg.fetch("updateDefaultWebhookUrl", ""))
|
||||
scheduled_at = ENV.fetch("XUQM_SCHEDULED_PUBLISH_AT", tenant_cfg.fetch("updateDefaultScheduledPublishAt", ""))
|
||||
publish_mode = ENV.fetch("XUQM_PUBLISH_MODE", tenant_cfg.fetch("updateDefaultPublishMode", "")).to_s.strip.upcase
|
||||
dry_run = ENV.fetch("XUQM_DRY_RUN", "false") == "true" || publish_mode == "DRY_RUN" || !tenant_cfg.fetch("updateEnabled", true)
|
||||
allow_version_mismatch = ENV.fetch("XUQM_ALLOW_VERSION_MISMATCH", "false") == "true"
|
||||
|
||||
# ── 1. Read local version ────────────────────────────────────────────
|
||||
version_name = get_version_number(target: scheme)
|
||||
@ -53,10 +58,24 @@ platform :ios do
|
||||
UI.message("Server latest versionCode: #{server_version_code}")
|
||||
|
||||
if version_code <= server_version_code
|
||||
if !allow_version_mismatch
|
||||
UI.message("Local version is not greater than server latest. Please enter corrected release version info.")
|
||||
version_name_input = prompt(text: "Release version name [#{version_name}]: ", ci_input: "").to_s.strip
|
||||
version_code_input = prompt(text: "Release version code [#{version_code}]: ", ci_input: "").to_s.strip
|
||||
version_name = version_name_input unless version_name_input.empty?
|
||||
version_code = version_code_input.to_i unless version_code_input.empty?
|
||||
end
|
||||
UI.user_error!(
|
||||
"Local versionCode (#{version_code}) must be greater than server (#{server_version_code}). " \
|
||||
"Please bump CFBundleVersion before releasing."
|
||||
)
|
||||
) if version_code <= server_version_code
|
||||
end
|
||||
|
||||
if version_name != get_version_number(target: scheme)
|
||||
increment_version_number(version_number: version_name)
|
||||
end
|
||||
if version_code != get_build_number.to_i
|
||||
increment_build_number(build_number: version_code.to_s)
|
||||
end
|
||||
|
||||
# ── 3. Archive & export IPA ──────────────────────────────────────────
|
||||
@ -76,8 +95,48 @@ platform :ios do
|
||||
UI.user_error!("IPA not found in #{ipa_output}") unless ipa_path
|
||||
UI.success("IPA: #{ipa_path}")
|
||||
|
||||
if dry_run
|
||||
UI.message("Dry-run summary:")
|
||||
UI.message(" updateEnabled=#{tenant_cfg.fetch("updateEnabled", true)}")
|
||||
UI.message(" releaseVersion=#{version_name} (#{version_code})")
|
||||
UI.message(" publishMode=#{publish_mode.empty? ? "MANUAL" : publish_mode}")
|
||||
UI.message(" publishImmediately=#{publish_immediately}")
|
||||
UI.message(" autoPublishAfterReview=#{auto_publish}")
|
||||
UI.message(" scheduledAt=#{scheduled_at.empty? ? "-" : scheduled_at}")
|
||||
UI.message(" webhookUrl=#{webhook_url.empty? ? "-" : webhook_url}")
|
||||
UI.message(" storeTargets=#{store_targets.empty? ? "-" : store_targets}")
|
||||
UI.message("Dry-run completed. No upload performed.")
|
||||
next
|
||||
end
|
||||
|
||||
# ── 4. Upload to XuqmGroup update service ────────────────────────────
|
||||
change_log = prompt(text: "Release notes: ", ci_input: "")
|
||||
if publish_mode.empty?
|
||||
publish_mode = if publish_immediately
|
||||
"NOW"
|
||||
elsif !scheduled_at.empty?
|
||||
"SCHEDULED"
|
||||
elsif auto_publish
|
||||
"AUTO_REVIEW"
|
||||
else
|
||||
prompt(text: "Publish mode (MANUAL/NOW/SCHEDULED/AUTO_REVIEW) [MANUAL]: ", ci_input: "").to_s.strip.upcase
|
||||
end
|
||||
end
|
||||
dry_run = true if publish_mode == "DRY_RUN"
|
||||
if !scheduled_at.empty?
|
||||
publish_immediately = false
|
||||
auto_publish = false
|
||||
end
|
||||
if publish_mode == "SCHEDULED" && scheduled_at.empty?
|
||||
scheduled_at = prompt(text: "Scheduled publish time (ISO datetime): ", ci_input: "").to_s.strip
|
||||
end
|
||||
if publish_mode == "NOW"
|
||||
publish_immediately = true
|
||||
auto_publish = false
|
||||
elsif publish_mode == "AUTO_REVIEW"
|
||||
auto_publish = true
|
||||
publish_immediately = false
|
||||
end
|
||||
version_id = xuqm_upload_ipa(
|
||||
server_url: server_url,
|
||||
app_key: app_key,
|
||||
@ -161,6 +220,20 @@ platform :ios do
|
||||
|
||||
# ── Private helpers ──────────────────────────────────────────────────────
|
||||
|
||||
private_lane :xuqm_fetch_sdk_config do |options|
|
||||
tenant_url = options[:tenant_url].to_s.strip
|
||||
return {} if tenant_url.empty?
|
||||
|
||||
uri = URI("#{tenant_url}/api/sdk/config?appId=#{options[:app_key]}&platform=#{options[:platform]}")
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
resp = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") { |h| h.request(req) }
|
||||
body = JSON.parse(resp.body)
|
||||
body["data"] || {}
|
||||
rescue => e
|
||||
UI.message("Failed to load tenant defaults: #{e.message}")
|
||||
{}
|
||||
end
|
||||
|
||||
private_lane :xuqm_get_latest_version_code do |options|
|
||||
uri = URI("#{options[:server_url]}/api/v1/updates/app/list?appId=#{options[:app_key]}&platform=#{options[:platform]}")
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户