fix: create android release checksums (#634)
This commit is contained in:
@@ -14,6 +14,7 @@ The first release automation layer is build-only:
|
||||
- builds staging iOS IPA for `dev.ipf.whitenoise.staging`
|
||||
- builds production iOS IPA for `org.parres.whitenoise`
|
||||
- stages artifacts under `build/releases/v<version>+<build>/<flavor>/`
|
||||
- creates `.sha256` sidecar files for staged Android APK and AAB artifacts
|
||||
|
||||
Staging and production are separate apps on both Android and iOS. Current iOS
|
||||
publishing target for both apps is App Store Connect/TestFlight. Store release
|
||||
|
||||
+22
-3
@@ -1,4 +1,5 @@
|
||||
require 'fileutils'
|
||||
require 'digest'
|
||||
require 'open3'
|
||||
require 'shellwords'
|
||||
|
||||
@@ -69,13 +70,21 @@ def release_output_dir(info, flavor, *parts)
|
||||
File.join(ROOT, 'build', 'releases', "v#{info['full_version']}", flavor.to_s, *parts)
|
||||
end
|
||||
|
||||
def stage_artifact(source, destination_dir, destination_name)
|
||||
def stage_artifact(source, destination_dir, destination_name, checksum: false)
|
||||
UI.user_error!("Missing artifact: #{source}") unless File.file?(source)
|
||||
|
||||
FileUtils.mkdir_p(destination_dir)
|
||||
destination = File.join(destination_dir, destination_name)
|
||||
FileUtils.cp(source, destination)
|
||||
UI.message("Staged #{destination}")
|
||||
|
||||
if checksum
|
||||
digest = Digest::SHA256.file(destination).hexdigest
|
||||
checksum_path = "#{destination}.sha256"
|
||||
File.write(checksum_path, "#{digest} #{destination_name}\n")
|
||||
UI.message("Staged #{checksum_path}")
|
||||
end
|
||||
|
||||
destination
|
||||
end
|
||||
|
||||
@@ -112,13 +121,23 @@ def build_android_flavor(flavor, options, build_native: true)
|
||||
UI.user_error!("Required APK was not found: #{source}")
|
||||
end
|
||||
|
||||
stage_artifact(source, output_dir, "#{config[:artifact_prefix]}-#{info['version_name']}-#{abi}.apk")
|
||||
stage_artifact(
|
||||
source,
|
||||
output_dir,
|
||||
"#{config[:artifact_prefix]}-#{info['version_name']}-#{abi}.apk",
|
||||
checksum: true,
|
||||
)
|
||||
end
|
||||
|
||||
source = android_aab(flavor)
|
||||
UI.user_error!("#{flavor.capitalize} AAB was not found") unless source
|
||||
|
||||
stage_artifact(source, output_dir, "#{config[:artifact_prefix]}-#{info['version_name']}.aab")
|
||||
stage_artifact(
|
||||
source,
|
||||
output_dir,
|
||||
"#{config[:artifact_prefix]}-#{info['version_name']}.aab",
|
||||
checksum: true,
|
||||
)
|
||||
end
|
||||
|
||||
def build_ios_flavor(flavor, options, build_native: true)
|
||||
|
||||
@@ -61,4 +61,74 @@ raise 'Zap Store match must include production arm64 APK' unless regex.match?(pr
|
||||
raise 'Zap Store match must exclude staging APK' if regex.match?(staging_apk)
|
||||
RUBY
|
||||
|
||||
ruby <<'RUBY'
|
||||
require 'digest'
|
||||
require 'fileutils'
|
||||
require 'tmpdir'
|
||||
|
||||
def opt_out_usage; end
|
||||
def desc(_text); end
|
||||
def lane(_name); end
|
||||
|
||||
module UI
|
||||
def self.user_error!(message)
|
||||
raise message
|
||||
end
|
||||
|
||||
def self.important(_message); end
|
||||
def self.message(_message); end
|
||||
end
|
||||
|
||||
load 'fastlane/Fastfile'
|
||||
|
||||
def release_info(_options = {})
|
||||
{
|
||||
'full_version' => '2026.5.7+24',
|
||||
'version_name' => '2026.5.7',
|
||||
'build_number' => '24',
|
||||
}
|
||||
end
|
||||
|
||||
def run_from_root(_parts); end
|
||||
|
||||
def assert_sidecar_matches(artifact_path)
|
||||
checksum_path = "#{artifact_path}.sha256"
|
||||
raise "missing checksum sidecar for #{artifact_path}" unless File.file?(checksum_path)
|
||||
|
||||
expected_digest = Digest::SHA256.file(artifact_path).hexdigest
|
||||
expected_contents = "#{expected_digest} #{File.basename(artifact_path)}\n"
|
||||
actual_contents = File.read(checksum_path)
|
||||
|
||||
raise "unexpected checksum contents: #{actual_contents.inspect}" unless actual_contents == expected_contents
|
||||
end
|
||||
|
||||
Dir.mktmpdir do |dir|
|
||||
Object.send(:remove_const, :ROOT)
|
||||
Object.const_set(:ROOT, dir)
|
||||
|
||||
apk_dir = File.join(ROOT, 'build', 'app', 'outputs', 'flutter-apk')
|
||||
aab_dir = File.join(ROOT, 'build', 'app', 'outputs', 'bundle', 'productionRelease')
|
||||
FileUtils.mkdir_p(apk_dir)
|
||||
FileUtils.mkdir_p(aab_dir)
|
||||
|
||||
File.write(File.join(apk_dir, 'app-arm64-v8a-production-release.apk'), 'arm64 apk bytes')
|
||||
File.write(File.join(apk_dir, 'app-x86_64-production-release.apk'), 'x86 apk bytes')
|
||||
File.write(File.join(aab_dir, 'app-production-release.aab'), 'aab bytes')
|
||||
|
||||
build_android_flavor('production', {}, build_native: true)
|
||||
|
||||
output_dir = File.join(ROOT, 'build', 'releases', 'v2026.5.7+24', 'production', 'android')
|
||||
[
|
||||
'whitenoise-2026.5.7-arm64-v8a.apk',
|
||||
'whitenoise-2026.5.7-x86_64.apk',
|
||||
'whitenoise-2026.5.7.aab',
|
||||
].each do |artifact_name|
|
||||
artifact_path = File.join(output_dir, artifact_name)
|
||||
raise "missing staged artifact #{artifact_path}" unless File.file?(artifact_path)
|
||||
|
||||
assert_sidecar_matches(artifact_path)
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
echo "release_automation_config_test passed"
|
||||
|
||||
Reference in New Issue
Block a user