refactor(updater): conform to new backend interfaces (#90)
This commit is contained in:
@@ -1,38 +1,39 @@
|
||||
name: Dart Package Workflow
|
||||
description: Build and test your Dart packages.
|
||||
|
||||
inputs:
|
||||
concurrency:
|
||||
required: false
|
||||
type: number
|
||||
default: 4
|
||||
default: "4"
|
||||
description: The value of the concurrency flag (-j) used when running tests
|
||||
coverage_excludes:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
description: Globs to exclude from coverage
|
||||
dart_sdk:
|
||||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
description: "The dart sdk version to use"
|
||||
working_directory:
|
||||
required: false
|
||||
type: string
|
||||
default: "."
|
||||
description: The working directory for this workflow
|
||||
min_coverage:
|
||||
required: false
|
||||
type: number
|
||||
default: 100
|
||||
default: "100"
|
||||
description: The minimum coverage percentage value
|
||||
analyze_directories:
|
||||
required: false
|
||||
type: string
|
||||
default: "lib test"
|
||||
description: Directories to analyze
|
||||
report_on:
|
||||
required: false
|
||||
type: string
|
||||
default: "lib"
|
||||
description: Directories to report on when collecting coverage
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: "vm"
|
||||
description: Platform to use when running tests
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Rust Crate Workflow
|
||||
description: Build and test your Rust crate
|
||||
|
||||
inputs:
|
||||
working_directory:
|
||||
required: false
|
||||
default: "."
|
||||
description: The working directory for this workflow.
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Build
|
||||
working-directory: ${{ inputs.working_directory }}
|
||||
shell: ${{ inputs.shell }}
|
||||
run: cargo build --verbose
|
||||
|
||||
- name: Test
|
||||
working-directory: ${{ inputs.working_directory }}
|
||||
shell: ${{ inputs.shell }}
|
||||
run: cargo test --verbose
|
||||
@@ -17,7 +17,8 @@ jobs:
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
needs_build: ${{ steps.needs_build.outputs.changes }}
|
||||
needs_dart_build: ${{ steps.needs_dart_build.outputs.changes }}
|
||||
needs_rust_build: ${{ steps.needs_rust_build.outputs.changes }}
|
||||
needs_verify: ${{ steps.needs_verify.outputs.changes }}
|
||||
|
||||
name: 👀 Detect Changes
|
||||
@@ -28,7 +29,7 @@ jobs:
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
name: Build Detection
|
||||
id: needs_build
|
||||
id: needs_dart_build
|
||||
with:
|
||||
filters: |
|
||||
shorebird_cli:
|
||||
@@ -42,6 +43,15 @@ jobs:
|
||||
- ./.github/actions/dart_package
|
||||
- packages/shorebird_code_push_protocol/**
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
name: Build Detection
|
||||
id: needs_rust_build
|
||||
with:
|
||||
filters: |
|
||||
updater:
|
||||
- ./.github/actions/rust
|
||||
- updater/**
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
name: Verify Detection
|
||||
id: needs_verify
|
||||
@@ -51,13 +61,13 @@ jobs:
|
||||
- ./.github/actions/dart_package
|
||||
- packages/shorebird_cli/**
|
||||
|
||||
build_packages:
|
||||
build_dart_packages:
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.needs_build != '[]' }}
|
||||
if: ${{ needs.changes.outputs.needs_dart_build != '[]' }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
package: ${{ fromJSON(needs.changes.outputs.needs_build) }}
|
||||
package: ${{ fromJSON(needs.changes.outputs.needs_dart_build) }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -72,6 +82,27 @@ jobs:
|
||||
with:
|
||||
working_directory: packages/${{ matrix.package }}
|
||||
|
||||
build_rust_crates:
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.needs_rust_build != '[]' }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
crate: ${{ fromJSON(needs.changes.outputs.needs_rust_build) }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: 🦀 Build ${{ matrix.crate }}
|
||||
|
||||
steps:
|
||||
- name: 📚 Git Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 🦀 Build ${{ matrix.package }}
|
||||
uses: ./.github/actions/rust_crate
|
||||
with:
|
||||
working_directory: ${{ matrix.crate }}
|
||||
|
||||
verify_packages:
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.needs_verify != '[]' }}
|
||||
@@ -94,7 +125,8 @@ jobs:
|
||||
working_directory: packages/${{ matrix.package }}
|
||||
|
||||
ci:
|
||||
needs: [semantic_pull_request, build_packages, verify_packages]
|
||||
needs:
|
||||
[semantic_pull_request, build_dart_packages, build_rust_crates, verify_packages]
|
||||
if: ${{ always() }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export 'app.dart';
|
||||
export 'patch.dart';
|
||||
export 'patch_artifact.dart';
|
||||
export 'user.dart';
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'patch_artifact.g.dart';
|
||||
|
||||
/// {@template patch_artifact}
|
||||
/// A patch artifact represents the contents of an update (patch) for a specific
|
||||
/// platform and architecture.
|
||||
/// {@endtemplate}
|
||||
@JsonSerializable()
|
||||
class PatchArtifact {
|
||||
/// {@macro patch_PatchArtifact}
|
||||
const PatchArtifact({
|
||||
required this.patchNumber,
|
||||
required this.downloadUrl,
|
||||
required this.hash,
|
||||
});
|
||||
|
||||
/// Converts a Map<String, dynamic> to an [PatchArtifact]
|
||||
factory PatchArtifact.fromJson(Map<String, dynamic> json) =>
|
||||
_$PatchArtifactFromJson(json);
|
||||
|
||||
/// Converts an [PatchArtifact] to a Map<String, dynamic>
|
||||
Map<String, dynamic> toJson() => _$PatchArtifactToJson(this);
|
||||
|
||||
/// The patch number associated with the artifact.
|
||||
final int patchNumber;
|
||||
|
||||
/// The URL of the artifact.
|
||||
final String downloadUrl;
|
||||
|
||||
/// The hash of the artifact.
|
||||
final String hash;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars
|
||||
|
||||
part of 'patch_artifact.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
PatchArtifact _$PatchArtifactFromJson(Map<String, dynamic> json) =>
|
||||
$checkedCreate(
|
||||
'PatchArtifact',
|
||||
json,
|
||||
($checkedConvert) {
|
||||
final val = PatchArtifact(
|
||||
patchNumber: $checkedConvert('patch_number', (v) => v as int),
|
||||
downloadUrl: $checkedConvert('download_url', (v) => v as String),
|
||||
hash: $checkedConvert('hash', (v) => v as String),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
fieldKeyMap: const {
|
||||
'patchNumber': 'patch_number',
|
||||
'downloadUrl': 'download_url'
|
||||
},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$PatchArtifactToJson(PatchArtifact instance) =>
|
||||
<String, dynamic>{
|
||||
'patch_number': instance.patchNumber,
|
||||
'download_url': instance.downloadUrl,
|
||||
'hash': instance.hash,
|
||||
};
|
||||
@@ -1,18 +0,0 @@
|
||||
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('PatchArtifact', () {
|
||||
test('can be (de)serialized', () {
|
||||
const patchArtifact = PatchArtifact(
|
||||
patchNumber: 1,
|
||||
downloadUrl: 'https://example.com',
|
||||
hash: '#',
|
||||
);
|
||||
expect(
|
||||
PatchArtifact.fromJson(patchArtifact.toJson()).toJson(),
|
||||
equals(patchArtifact.toJson()),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -21,7 +21,7 @@ fn main() {
|
||||
|
||||
let config = updater::AppConfig {
|
||||
cache_dir: "updater_cache".to_owned(),
|
||||
base_version: "0.1.0".to_owned(),
|
||||
release_version: "0.1.0".to_owned(),
|
||||
original_libapp_path: "libapp.so".to_owned(),
|
||||
vm_path: "libflutter.so".to_owned(),
|
||||
};
|
||||
@@ -50,7 +50,7 @@ base_url: http://localhost:8000
|
||||
match version {
|
||||
Some(v) => {
|
||||
println!("path: {:?}", v.path);
|
||||
println!("version: {:?}", v.version);
|
||||
println!("number: {:?}", v.number);
|
||||
}
|
||||
None => {
|
||||
println!("None");
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
*/
|
||||
typedef struct AppParameters {
|
||||
/**
|
||||
* base_version, required. Named version of the app, off of which updates
|
||||
* release_version, required. Named version of the app, off of which updates
|
||||
* are based. Can be either a version number or a hash.
|
||||
*/
|
||||
const char *base_version;
|
||||
const char *release_version;
|
||||
/**
|
||||
* Path to the original aot library, required. For Flutter apps this
|
||||
* is the path to the bundled libapp.so. May be used for compression
|
||||
|
||||
@@ -14,9 +14,9 @@ use crate::updater;
|
||||
/// NOTE: If this struct is changed all language bindings must be updated.
|
||||
#[repr(C)]
|
||||
pub struct AppParameters {
|
||||
/// base_version, required. Named version of the app, off of which updates
|
||||
/// release_version, required. Named version of the app, off of which updates
|
||||
/// are based. Can be either a version number or a hash.
|
||||
pub base_version: *const libc::c_char,
|
||||
pub release_version: *const libc::c_char,
|
||||
|
||||
/// Path to the original aot library, required. For Flutter apps this
|
||||
/// is the path to the bundled libapp.so. May be used for compression
|
||||
@@ -43,7 +43,7 @@ fn app_config_from_c(c_params: *const AppParameters) -> updater::AppConfig {
|
||||
|
||||
updater::AppConfig {
|
||||
cache_dir: to_rust(c_params_ref.cache_dir),
|
||||
base_version: to_rust(c_params_ref.base_version),
|
||||
release_version: to_rust(c_params_ref.release_version),
|
||||
original_libapp_path: to_rust(c_params_ref.original_libapp_path),
|
||||
vm_path: to_rust(c_params_ref.vm_path),
|
||||
}
|
||||
@@ -67,13 +67,14 @@ pub extern "C" fn shorebird_init(c_params: *const AppParameters, c_yaml: *const
|
||||
}
|
||||
|
||||
/// Return the active version of the app, or NULL if there is no active version.
|
||||
// TODO: This should probably be renamed to `shorebird_active_patch_number`.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn shorebird_active_version() -> *mut c_char {
|
||||
let version = updater::active_patch();
|
||||
match version {
|
||||
let patch = updater::active_patch();
|
||||
match patch {
|
||||
Some(v) => {
|
||||
let c_version = CString::new(v.version).unwrap();
|
||||
c_version.into_raw()
|
||||
let c_patch = CString::new(v.number.to_string()).unwrap();
|
||||
c_patch.into_raw()
|
||||
}
|
||||
None => std::ptr::null_mut(),
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ use crate::network::{download_file_to_path, PatchCheckResponse};
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct PatchInfo {
|
||||
pub path: String,
|
||||
pub version: String,
|
||||
pub number: usize,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Default, Clone)]
|
||||
struct Slot {
|
||||
/// Path to the slot directory.
|
||||
path: String,
|
||||
/// Version of the patch in this slot.
|
||||
patch_version: String,
|
||||
/// Patch number for the patch in this slot.
|
||||
patch_number: usize,
|
||||
}
|
||||
|
||||
// This struct is public, as callers can have a handle to it, but modifying
|
||||
@@ -27,10 +27,10 @@ struct Slot {
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct UpdaterState {
|
||||
/// List of patches that failed to boot. We will never attempt these again.
|
||||
failed_patches: Vec<String>,
|
||||
failed_patches: Vec<usize>,
|
||||
/// List of patches that successfully booted. We will never rollback past
|
||||
/// one of these for this device.
|
||||
successful_patches: Vec<String>,
|
||||
successful_patches: Vec<usize>,
|
||||
/// Currently selected slot.
|
||||
current_slot_index: usize,
|
||||
/// List of slots.
|
||||
@@ -51,11 +51,11 @@ impl Default for UpdaterState {
|
||||
|
||||
impl UpdaterState {
|
||||
pub fn is_known_good_patch(&self, patch: &PatchInfo) -> bool {
|
||||
self.successful_patches.iter().any(|v| v == &patch.version)
|
||||
self.successful_patches.iter().any(|v| v == &patch.number)
|
||||
}
|
||||
|
||||
pub fn is_known_bad_patch(&self, patch: &PatchInfo) -> bool {
|
||||
self.failed_patches.iter().any(|v| v == &patch.version)
|
||||
self.failed_patches.iter().any(|v| v == &patch.number)
|
||||
}
|
||||
|
||||
pub fn mark_patch_as_bad(&mut self, patch: &PatchInfo) {
|
||||
@@ -67,7 +67,7 @@ impl UpdaterState {
|
||||
if self.is_known_bad_patch(patch) {
|
||||
return;
|
||||
}
|
||||
self.failed_patches.push(patch.version.clone());
|
||||
self.failed_patches.push(patch.number.clone());
|
||||
}
|
||||
|
||||
pub fn mark_patch_as_good(&mut self, patch: &PatchInfo) {
|
||||
@@ -79,7 +79,7 @@ impl UpdaterState {
|
||||
if self.is_known_good_patch(patch) {
|
||||
return;
|
||||
}
|
||||
self.successful_patches.push(patch.version.clone());
|
||||
self.successful_patches.push(patch.number.clone());
|
||||
}
|
||||
|
||||
pub fn load(cache_dir: &str) -> anyhow::Result<Self> {
|
||||
@@ -111,7 +111,7 @@ impl UpdaterState {
|
||||
// Otherwise return the version info from the current slot.
|
||||
return Some(PatchInfo {
|
||||
path: slot.path.clone(),
|
||||
version: slot.patch_version.clone(),
|
||||
number: slot.patch_number.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ fn download_into_slot(
|
||||
slot_index,
|
||||
Slot {
|
||||
path: path.to_str().unwrap().to_string(),
|
||||
patch_version: patch.version.clone(),
|
||||
patch_number: patch.number.clone(),
|
||||
},
|
||||
);
|
||||
state.save(cache_dir)?;
|
||||
|
||||
@@ -38,7 +38,7 @@ pub struct ResolvedConfig {
|
||||
pub cache_dir: String,
|
||||
pub channel: String,
|
||||
pub app_id: String,
|
||||
pub base_version: String,
|
||||
pub release_version: String,
|
||||
pub original_libapp_path: String,
|
||||
pub vm_path: String,
|
||||
pub base_url: String,
|
||||
@@ -51,7 +51,7 @@ impl ResolvedConfig {
|
||||
cache_dir: String::new(),
|
||||
channel: String::new(),
|
||||
app_id: String::new(),
|
||||
base_version: String::new(),
|
||||
release_version: String::new(),
|
||||
original_libapp_path: String::new(),
|
||||
vm_path: String::new(),
|
||||
base_url: String::new(),
|
||||
@@ -77,7 +77,7 @@ pub fn set_config(config: AppConfig, yaml: YamlConfig) {
|
||||
.to_owned();
|
||||
lock.cache_dir = config.cache_dir.to_string();
|
||||
lock.app_id = yaml.app_id.to_string();
|
||||
lock.base_version = config.base_version.to_string();
|
||||
lock.release_version = config.release_version.to_string();
|
||||
lock.original_libapp_path = config.original_libapp_path.to_string();
|
||||
lock.vm_path = config.vm_path.to_string();
|
||||
lock.is_initialized = true;
|
||||
|
||||
@@ -17,7 +17,7 @@ fn patches_check_url(base_url: &str) -> String {
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Patch {
|
||||
pub version: String,
|
||||
pub number: usize,
|
||||
pub hash: String,
|
||||
pub download_url: String,
|
||||
}
|
||||
@@ -40,9 +40,9 @@ pub fn send_patch_check_request(
|
||||
let mut body = HashMap::new();
|
||||
body.insert("app_id", config.app_id.clone());
|
||||
body.insert("channel", config.channel.clone());
|
||||
body.insert("base_version", config.base_version.clone());
|
||||
body.insert("release_version", config.release_version.clone());
|
||||
if let Some(patch) = patch {
|
||||
body.insert("patch_version", patch.version);
|
||||
body.insert("patch_number", patch.number.to_string());
|
||||
}
|
||||
body.insert("platform", current_platform().to_string());
|
||||
body.insert("arch", current_arch().to_string());
|
||||
|
||||
@@ -52,7 +52,7 @@ impl Display for UpdateError {
|
||||
// but making &str from CStr* is a bit of a pain.
|
||||
pub struct AppConfig {
|
||||
pub cache_dir: String,
|
||||
pub base_version: String,
|
||||
pub release_version: String,
|
||||
pub original_libapp_path: String,
|
||||
pub vm_path: String,
|
||||
}
|
||||
@@ -168,7 +168,7 @@ mod tests {
|
||||
crate::init(
|
||||
crate::AppConfig {
|
||||
cache_dir: cache_dir.clone(),
|
||||
base_version: "1.0.0".to_string(),
|
||||
release_version: "1.0.0".to_string(),
|
||||
original_libapp_path: "original_libapp_path".to_string(),
|
||||
vm_path: "vm_path".to_string(),
|
||||
},
|
||||
@@ -185,7 +185,7 @@ mod tests {
|
||||
crate::init(
|
||||
crate::AppConfig {
|
||||
cache_dir: cache_dir.clone(),
|
||||
base_version: "1.0.0".to_string(),
|
||||
release_version: "1.0.0".to_string(),
|
||||
original_libapp_path: "original_libapp_path".to_string(),
|
||||
vm_path: "vm_path".to_string(),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user