From ffbab68859f66bd8a3bf144ec443cbebdbcf40b8 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Wed, 18 Dec 2024 20:20:14 +0900 Subject: [PATCH 01/18] release: update rusaint-ios to 0.8.0 --- languages/swift/Rusaint | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/swift/Rusaint b/languages/swift/Rusaint index e49d388..42d58e1 160000 --- a/languages/swift/Rusaint +++ b/languages/swift/Rusaint @@ -1 +1 @@ -Subproject commit e49d38824d97f5775d49375cfb3e3498b716ed21 +Subproject commit 42d58e1de286cb2f5ef9f9a18e79f64198323e2c From 07be7babeb67107ab8794add095af6d458123b98 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 11:56:34 +0900 Subject: [PATCH 02/18] feat(application): `try_table_into_with_scroll` util --- .../src/application/utils/sap_table.rs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 packages/rusaint/src/application/utils/sap_table.rs diff --git a/packages/rusaint/src/application/utils/sap_table.rs b/packages/rusaint/src/application/utils/sap_table.rs new file mode 100644 index 0000000..151e8aa --- /dev/null +++ b/packages/rusaint/src/application/utils/sap_table.rs @@ -0,0 +1,55 @@ +use crate::application::USaintClient; +use crate::webdynpro::command::element::complex::{ + SapTableBodyCommand, SapTableLSDataCommand, SapTableVerticalScrollEventCommand, +}; +use crate::webdynpro::command::WebDynproCommandExecutor; +use crate::webdynpro::element::complex::sap_table::FromSapTable; +use crate::webdynpro::element::complex::SapTableDef; +use crate::webdynpro::element::definition::ElementDefinition; +use crate::webdynpro::element::parser::ElementParser; +use crate::webdynpro::error::{ElementError, WebDynproError}; + +pub(crate) async fn try_table_into_with_scroll FromSapTable<'body>>( + client: &mut USaintClient, + mut parser: ElementParser, + table: SapTableDef, +) -> Result, WebDynproError> { + let row_count = parser + .read(SapTableLSDataCommand::new(table.clone()))? + .row_count() + .map(|u| u.to_owned()) + .ok_or_else(|| { + WebDynproError::Element(ElementError::NoSuchData { + element: table.clone().id().to_string(), + field: "row_count".to_string(), + }) + })? + .try_into() + .unwrap(); + let mut table_body = parser.read(SapTableBodyCommand::new(table.clone()))?; + let mut results: Vec = Vec::with_capacity(row_count); + while results.len() < row_count { + let mut partial_results = table_body.try_table_into::(&parser)?; + if results.len() + partial_results.len() > row_count { + let overflowed = results.len() + partial_results.len() - row_count; + partial_results.drain(0..overflowed); + } + results.append(&mut partial_results); + if results.len() < row_count { + let event = parser.read(SapTableVerticalScrollEventCommand::new( + table.clone(), + results.len().try_into().unwrap(), + "", + "SCROLLBAR", + false, + false, + false, + false, + ))?; + client.process_event(false, event).await?; + parser = ElementParser::new(client.body()); + table_body = parser.read(SapTableBodyCommand::new(table.clone()))?; + } + } + Ok(results) +} From 5c6bb2d685fd498e0a37bcd36faa2b1be3bc0b83 Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 11:59:14 +0900 Subject: [PATCH 03/18] feat(application): scroll table if full results are not retrieved --- .../src/application/course_grades/mod.rs | 13 +++++-- .../src/application/course_schedule/mod.rs | 5 ++- .../src/application/lecture_assessment/mod.rs | 37 +++---------------- .../model/academic_record.rs | 8 ++-- .../student_information/model/family.rs | 8 ++-- .../student_information/model/transfer.rs | 11 ++++-- packages/rusaint/src/application/utils/mod.rs | 1 + 7 files changed, 38 insertions(+), 45 deletions(-) diff --git a/packages/rusaint/src/application/course_grades/mod.rs b/packages/rusaint/src/application/course_grades/mod.rs index 8604a0d..4b21c99 100644 --- a/packages/rusaint/src/application/course_grades/mod.rs +++ b/packages/rusaint/src/application/course_grades/mod.rs @@ -1,5 +1,6 @@ use self::model::{ClassGrade, CourseType, GradeSummary, SemesterGrade}; use super::{USaintApplication, USaintClient}; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::client::body::Body; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::complex::sap_table::cell::SapTableCellWrapper; @@ -295,13 +296,17 @@ impl<'a> CourseGradesApplication { self.close_popups().await?; let parser = ElementParser::new(self.client.body()); self.select_course(&parser, course_type).await?; - self.read_semesters() + self.read_semesters().await } - fn read_semesters(&self) -> Result, RusaintError> { + async fn read_semesters(&mut self) -> Result, RusaintError> { let parser = ElementParser::new(self.client.body()); - let table = parser.read(SapTableBodyCommand::new(Self::GRADES_SUMMARY_TABLE))?; - let ret = table.try_table_into::(&parser)?; + let ret = try_table_into_with_scroll::( + &mut self.client, + parser, + Self::GRADES_SUMMARY_TABLE, + ) + .await?; Ok(ret) } diff --git a/packages/rusaint/src/application/course_schedule/mod.rs b/packages/rusaint/src/application/course_schedule/mod.rs index 6487753..d8b9ce4 100644 --- a/packages/rusaint/src/application/course_schedule/mod.rs +++ b/packages/rusaint/src/application/course_schedule/mod.rs @@ -1,4 +1,5 @@ use super::{USaintApplication, USaintClient}; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::parser::ElementParser; use crate::{ @@ -128,7 +129,9 @@ impl<'a> CourseScheduleApplication { } } } - let lectures = table.try_table_into::(&parser)?; + let lectures = + try_table_into_with_scroll::(&mut self.client, parser, Self::MAIN_TABLE) + .await?; Ok(lectures.into_iter()) } diff --git a/packages/rusaint/src/application/lecture_assessment/mod.rs b/packages/rusaint/src/application/lecture_assessment/mod.rs index 81a1c16..3bc640a 100644 --- a/packages/rusaint/src/application/lecture_assessment/mod.rs +++ b/packages/rusaint/src/application/lecture_assessment/mod.rs @@ -1,6 +1,7 @@ use model::LectureAssessmentResult; use super::{USaintApplication, USaintClient}; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::parser::ElementParser; use crate::{ @@ -10,9 +11,7 @@ use crate::{ client::body::Body, command::element::{ action::ButtonPressEventCommand, - complex::{ - SapTableBodyCommand, SapTableLSDataCommand, SapTableVerticalScrollEventCommand, - }, + complex::{SapTableBodyCommand, SapTableLSDataCommand}, selection::{ ComboBoxChangeEventCommand, ComboBoxLSDataCommand, ComboBoxSelectEventCommand, }, @@ -143,8 +142,8 @@ impl<'a> LectureAssessmentApplication { professor_name, ) .await?; - let mut parser = ElementParser::new(self.body()); - let row_count = parser + let parser = ElementParser::new(self.body()); + let row_count: u32 = parser .read(SapTableLSDataCommand::new(Self::TABLE))? .row_count() .map(|u| u.to_owned()) @@ -156,7 +155,7 @@ impl<'a> LectureAssessmentApplication { })? .try_into() .unwrap(); - let mut table = parser.read(SapTableBodyCommand::new(Self::TABLE))?; + let table = parser.read(SapTableBodyCommand::new(Self::TABLE))?; if row_count == 1 { let Some(first_row) = table.iter().next() else { return Err(ApplicationError::NoLectureAssessments.into()); @@ -173,31 +172,7 @@ impl<'a> LectureAssessmentApplication { } } } - let mut results: Vec = Vec::with_capacity(row_count); - while results.len() < row_count { - let mut partial_results = table.try_table_into::(&parser)?; - if results.len() + partial_results.len() > row_count { - let overflowed = results.len() + partial_results.len() - row_count; - partial_results.drain(0..overflowed); - } - results.append(&mut partial_results); - if results.len() < row_count { - let event = parser.read(SapTableVerticalScrollEventCommand::new( - Self::TABLE, - results.len().try_into().unwrap(), - "", - "SCROLLBAR", - false, - false, - false, - false, - ))?; - self.client.process_event(false, event).await?; - parser = ElementParser::new(self.body()); - table = parser.read(SapTableBodyCommand::new(Self::TABLE))?; - } - } - Ok(results) + Ok(try_table_into_with_scroll(&mut self.client, parser, Self::TABLE).await?) } } diff --git a/packages/rusaint/src/application/student_information/model/academic_record.rs b/packages/rusaint/src/application/student_information/model/academic_record.rs index 3fcdb2f..3262be0 100644 --- a/packages/rusaint/src/application/student_information/model/academic_record.rs +++ b/packages/rusaint/src/application/student_information/model/academic_record.rs @@ -5,13 +5,14 @@ use serde::{ Deserialize, }; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::parser::ElementParser; use crate::{ application::{student_information::StudentInformationApplication, USaintClient}, define_elements, webdynpro::{ - command::element::{complex::SapTableBodyCommand, layout::TabStripTabSelectEventCommand}, + command::element::layout::TabStripTabSelectEventCommand, element::{ complex::{sap_table::FromSapTable, SapTable}, definition::ElementDefinition, @@ -47,8 +48,9 @@ impl<'a> StudentAcademicRecords { ))?; client.process_event(false, event).await?; parser = ElementParser::new(client.body()); - let table = parser.read(SapTableBodyCommand::new(Self::TABLE_9600))?; - let records = table.try_table_into::(&parser)?; + let records = + try_table_into_with_scroll::(client, parser, Self::TABLE_9600) + .await?; Ok(Self { records }) } diff --git a/packages/rusaint/src/application/student_information/model/family.rs b/packages/rusaint/src/application/student_information/model/family.rs index 65b24b8..436d3ac 100644 --- a/packages/rusaint/src/application/student_information/model/family.rs +++ b/packages/rusaint/src/application/student_information/model/family.rs @@ -6,13 +6,14 @@ use serde::{ }; use crate::application::utils::de_with::{deserialize_bool_string, deserialize_optional_string}; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::parser::ElementParser; use crate::{ application::{student_information::StudentInformationApplication, USaintClient}, define_elements, webdynpro::{ - command::element::{complex::SapTableBodyCommand, layout::TabStripTabSelectEventCommand}, + command::element::layout::TabStripTabSelectEventCommand, element::{ complex::{sap_table::FromSapTable, SapTable}, definition::ElementDefinition, @@ -48,8 +49,9 @@ impl<'a> StudentFamily { ))?; client.process_event(false, event).await?; parser = ElementParser::new(client.body()); - let table = parser.read(SapTableBodyCommand::new(Self::TABLE_FAMILY))?; - let members = table.try_table_into::(&parser)?; + let members = + try_table_into_with_scroll::(client, parser, Self::TABLE_FAMILY) + .await?; Ok(Self { members }) } diff --git a/packages/rusaint/src/application/student_information/model/transfer.rs b/packages/rusaint/src/application/student_information/model/transfer.rs index f8d952b..564abcf 100644 --- a/packages/rusaint/src/application/student_information/model/transfer.rs +++ b/packages/rusaint/src/application/student_information/model/transfer.rs @@ -5,13 +5,14 @@ use serde::{ Deserialize, }; +use crate::application::utils::sap_table::try_table_into_with_scroll; use crate::webdynpro::command::WebDynproCommandExecutor; use crate::webdynpro::element::parser::ElementParser; use crate::{ application::{student_information::StudentInformationApplication, USaintClient}, define_elements, webdynpro::{ - command::element::{complex::SapTableBodyCommand, layout::TabStripTabSelectEventCommand}, + command::element::layout::TabStripTabSelectEventCommand, element::{ complex::{sap_table::FromSapTable, SapTable}, definition::ElementDefinition, @@ -47,8 +48,12 @@ impl<'a> StudentTransferRecords { ))?; client.process_event(false, event).await?; parser = ElementParser::new(client.body()); - let table = parser.read(SapTableBodyCommand::new(Self::TABLE_TRANSFER))?; - let records = table.try_table_into::(&parser)?; + let records = try_table_into_with_scroll::( + client, + parser, + Self::TABLE_TRANSFER, + ) + .await?; Ok(Self { records }) } diff --git a/packages/rusaint/src/application/utils/mod.rs b/packages/rusaint/src/application/utils/mod.rs index db02525..eb7eab6 100644 --- a/packages/rusaint/src/application/utils/mod.rs +++ b/packages/rusaint/src/application/utils/mod.rs @@ -1,2 +1,3 @@ pub(crate) mod de_with; pub(crate) mod input_field; +pub(crate) mod sap_table; From fa3600e2c8359c3f210e84d0b0ff3c649a51aedc Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 12:07:26 +0900 Subject: [PATCH 04/18] ci: enable `cargo-cache` for workflows --- .github/workflows/build_test.yml | 6 ++++++ .github/workflows/dry-run.yml | 2 ++ .github/workflows/release.yml | 2 ++ 3 files changed, 10 insertions(+) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 6fb5cbc..975863a 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -21,7 +21,13 @@ jobs: - uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable + - name: Retrieve cache + uses: Leafwing-Studios/cargo-cache@v2 - name: Build run: cargo build --verbose + - name: Check format + run: cargo check + - name: Check clippy + run: cargo clippy - name: Run tests run: cargo test --verbose diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index 3697ace..e4955ea 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -19,6 +19,8 @@ jobs: uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable + - name: Retrieve cache + uses: Leafwing-Studios/cargo-cache@v2 - name: Publish dry-run run: cargo publish -p rusaint --dry-run --verbose - name: Run tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9e719fb..9928f6a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,8 @@ jobs: uses: dtolnay/rust-toolchain@stable with: targets: 'armv7-linux-androideabi, i686-linux-android, aarch64-linux-android, x86_64-linux-android' + - name: Retrieve cache + uses: Leafwing-Studios/cargo-cache@v2 - name: Setup Java uses: actions/setup-java@v4 with: From 642c9470416411e91917d44770f78dcc9bb7ba1d Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 12:42:05 +0900 Subject: [PATCH 05/18] ci: split build_test into build_test and lint workflow --- .github/workflows/build_test.yml | 4 ---- .github/workflows/lint.yml | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 975863a..d963712 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -25,9 +25,5 @@ jobs: uses: Leafwing-Studios/cargo-cache@v2 - name: Build run: cargo build --verbose - - name: Check format - run: cargo check - - name: Check clippy - run: cargo clippy - name: Run tests run: cargo test --verbose diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..56b9eea --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,29 @@ +name: Lint + +on: + workflow_dispatch: + pull_request: + branches: [ "main", "dev" ] +env: + CARGO_TERM_COLOR: always +jobs: + build: + runs-on: ubuntu-latest + environment: testing + env: + SSO_ID: ${{ vars.SSO_ID }} + SSO_PASSWORD: ${{ secrets.SSO_PASSWORD }} + TARGET_YEAR: ${{ vars.TARGET_YEAR }} + TARGET_SEMESTER: ${{ vars.TARGET_SEMESTER }} + steps: + - uses: actions/checkout@v4 + - name: Setup Rust + uses: dtolnay/rust-toolchain@nightly + with: + components: clippy, rustfmt + - name: Retrieve cache + uses: Leafwing-Studios/cargo-cache@v2 + - name: Check rustfmt + run: cargo +nightly fmt + - name: Check clippy + run: cargo +nightly clippy -- -D warnings From 7f7a2f27c272aa496a60cc12ab84d81f4823d7ba Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 12:46:06 +0900 Subject: [PATCH 06/18] lint: apply clippy suggestion --- packages/rusaint/src/webdynpro/client/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rusaint/src/webdynpro/client/mod.rs b/packages/rusaint/src/webdynpro/client/mod.rs index d5b2ca8..d517d51 100644 --- a/packages/rusaint/src/webdynpro/client/mod.rs +++ b/packages/rusaint/src/webdynpro/client/mod.rs @@ -38,7 +38,7 @@ fn wd_xhr_header() -> HeaderMap { headers } -impl<'a> WebDynproClient { +impl WebDynproClient { /// WebDynpro 애플리케이션의 이름을 반환합니다. pub fn name(&self) -> &str { &self.name From 744be81ff531ffeac1b80d2ae77676eda3be002c Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 12:53:36 +0900 Subject: [PATCH 07/18] ci: explicit cache keys --- .github/workflows/build_test.yml | 2 ++ .github/workflows/dry-run.yml | 2 ++ .github/workflows/lint.yml | 2 ++ .github/workflows/release.yml | 2 ++ 4 files changed, 8 insertions(+) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index d963712..68199d9 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -23,6 +23,8 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 + with: + cache-key: "build-test-${{ hashFiles('**/Cargo.lock') }}" - name: Build run: cargo build --verbose - name: Run tests diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index e4955ea..5f1c9ed 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -21,6 +21,8 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 + with: + cache-key: "dry-run-${{ hashFiles('**/Cargo.lock') }}" - name: Publish dry-run run: cargo publish -p rusaint --dry-run --verbose - name: Run tests diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 56b9eea..e686782 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,8 @@ jobs: components: clippy, rustfmt - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 + with: + cache-key: "lint-${{ hashFiles('**/Cargo.lock') }}" - name: Check rustfmt run: cargo +nightly fmt - name: Check clippy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9928f6a..7447d8b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,6 +20,8 @@ jobs: targets: 'armv7-linux-androideabi, i686-linux-android, aarch64-linux-android, x86_64-linux-android' - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 + with: + cache-key: "release-${{ hashFiles('**/Cargo.lock') }}" - name: Setup Java uses: actions/setup-java@v4 with: From 778cc8ee6be44e3977f9bcbb6a693fa4126f2e0f Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 13:10:49 +0900 Subject: [PATCH 08/18] ci: setup android ndk with caching --- .github/workflows/release.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7447d8b..05e51f2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,10 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v3 - name: Setup Android NDK - run: 'sdkmanager "ndk;27.2.12479018"' + uses: nttld/setup-ndk@v1 + with: + ndk-version: r27c + link-to-sdk: true - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - name: Build with Gradle From 6d8327f02e76d2969019b0095a0b0f7ff85f0f1f Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 13:16:20 +0900 Subject: [PATCH 09/18] ci: remove unused environment and variables --- .github/workflows/dry-run.yml | 6 ------ .github/workflows/lint.yml | 10 +--------- .github/workflows/release.yml | 1 - 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index 5f1c9ed..6462e14 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -8,12 +8,6 @@ env: jobs: build: runs-on: ubuntu-latest - environment: testing - env: - SSO_ID: ${{ vars.SSO_ID }} - SSO_PASSWORD: ${{ secrets.SSO_PASSWORD }} - TARGET_YEAR: ${{ vars.TARGET_YEAR }} - TARGET_SEMESTER: ${{ vars.TARGET_SEMESTER }} steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e686782..8e31bf1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -4,17 +4,9 @@ on: workflow_dispatch: pull_request: branches: [ "main", "dev" ] -env: - CARGO_TERM_COLOR: always jobs: build: runs-on: ubuntu-latest - environment: testing - env: - SSO_ID: ${{ vars.SSO_ID }} - SSO_PASSWORD: ${{ secrets.SSO_PASSWORD }} - TARGET_YEAR: ${{ vars.TARGET_YEAR }} - TARGET_SEMESTER: ${{ vars.TARGET_SEMESTER }} steps: - uses: actions/checkout@v4 - name: Setup Rust @@ -28,4 +20,4 @@ jobs: - name: Check rustfmt run: cargo +nightly fmt - name: Check clippy - run: cargo +nightly clippy -- -D warnings + run: cargo +nightly clippy -- -D warnings \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05e51f2..96b8156 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,6 @@ env: jobs: build: runs-on: ubuntu-latest - environment: testing steps: - name: Checkout uses: actions/checkout@v4 From 90f360f8a68c9ca6830528a1f463c99d561e9cec Mon Sep 17 00:00:00 2001 From: EATSTEAK Date: Sat, 21 Dec 2024 13:23:16 +0900 Subject: [PATCH 10/18] lint(application/lecture_assessment): remove useless conversion --- packages/rusaint/src/application/lecture_assessment/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/rusaint/src/application/lecture_assessment/mod.rs b/packages/rusaint/src/application/lecture_assessment/mod.rs index 3bc640a..c68e8ab 100644 --- a/packages/rusaint/src/application/lecture_assessment/mod.rs +++ b/packages/rusaint/src/application/lecture_assessment/mod.rs @@ -143,7 +143,7 @@ impl<'a> LectureAssessmentApplication { ) .await?; let parser = ElementParser::new(self.body()); - let row_count: u32 = parser + let row_count = parser .read(SapTableLSDataCommand::new(Self::TABLE))? .row_count() .map(|u| u.to_owned()) @@ -152,9 +152,7 @@ impl<'a> LectureAssessmentApplication { element: Self::TABLE.id().to_string(), field: "row_count".to_string(), }) - })? - .try_into() - .unwrap(); + })?; let table = parser.read(SapTableBodyCommand::new(Self::TABLE))?; if row_count == 1 { let Some(first_row) = table.iter().next() else { From b557eb833b2e0fcf0e44c2e9998e46e5b9dc8db5 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 14:59:39 +0900 Subject: [PATCH 11/18] ci: remove undefined `cache-key` property --- .github/workflows/build_test.yml | 2 +- .github/workflows/dry-run.yml | 2 -- .github/workflows/lint.yml | 2 +- .github/workflows/release.yml | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 68199d9..6304fc4 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -24,7 +24,7 @@ jobs: - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 with: - cache-key: "build-test-${{ hashFiles('**/Cargo.lock') }}" + cache-group: build - name: Build run: cargo build --verbose - name: Run tests diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index 6462e14..b4b1192 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -15,8 +15,6 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 - with: - cache-key: "dry-run-${{ hashFiles('**/Cargo.lock') }}" - name: Publish dry-run run: cargo publish -p rusaint --dry-run --verbose - name: Run tests diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8e31bf1..286ec07 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,7 +16,7 @@ jobs: - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 with: - cache-key: "lint-${{ hashFiles('**/Cargo.lock') }}" + cache-group: build - name: Check rustfmt run: cargo +nightly fmt - name: Check clippy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96b8156..b123d40 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,6 @@ jobs: - name: Retrieve cache uses: Leafwing-Studios/cargo-cache@v2 with: - cache-key: "release-${{ hashFiles('**/Cargo.lock') }}" - name: Setup Java uses: actions/setup-java@v4 with: From f2abe52ec184dcb771789566b1b2fe152b508379 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 15:53:13 +0900 Subject: [PATCH 12/18] ci: do not test rusaint concurrently regarding session limitation --- .github/workflows/build_test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 6304fc4..034e8c5 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -12,6 +12,9 @@ jobs: build: runs-on: ubuntu-latest environment: testing + concurrency: + group: testing + cancel-in-progress: true env: SSO_ID: ${{ vars.SSO_ID }} SSO_PASSWORD: ${{ secrets.SSO_PASSWORD }} From 09f13c8246f0dac077d3b68b5f31f635e260ee19 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 15:53:46 +0900 Subject: [PATCH 13/18] ci(languages/swift): use `aarch-apple-ios` target to generate bindings --- languages/swift/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/swift/build.sh b/languages/swift/build.sh index e218027..90ed0a5 100755 --- a/languages/swift/build.sh +++ b/languages/swift/build.sh @@ -21,7 +21,7 @@ lipo -create ../../target/aarch64-apple-ios-sim/release/librusaint_ffi.a \ # Generate swift bindings cargo run -p uniffi-bindgen generate \ - ../../target/aarch64-apple-ios-sim/release/librusaint_ffi.dylib \ + ../../target/aarch64-apple-ios/release/librusaint_ffi.dylib \ --library \ --language swift \ --no-format \ From b6a17036f9127af0f477b6cb19d5d225dcffe037 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 15:57:53 +0900 Subject: [PATCH 14/18] ci: `release-ios` workflow --- .github/workflows/release-ios.yml | 150 ++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 .github/workflows/release-ios.yml diff --git a/.github/workflows/release-ios.yml b/.github/workflows/release-ios.yml new file mode 100644 index 0000000..5030276 --- /dev/null +++ b/.github/workflows/release-ios.yml @@ -0,0 +1,150 @@ +name: Release (iOS) + +on: + push: + branches: [ dev ] + paths: + - './Cargo.toml' + workflow_dispatch: +permissions: + actions: write +jobs: + release: + runs-on: macos-latest + steps: + - name: Checkout Cargo.toml to check version + uses: actions/checkout@v4 + with: + token: ${{ secrets.IOS_GITHUB_TOKEN }} + sparse-checkout: | + Cargo.toml + sparse-checkout-cone-mode: false + - name: Get rusaint version + id: current_version + uses: mikefarah/yq@v4 + with: + cmd: yq '.workspace.package.version | "v" + .' Cargo.toml + - name: Fetch latest release tag + id: latest_release + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.IOS_GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/EATSTEAK/rusaint/releases \ + | jq '.[0].tag_name | "result=" + .' \ + | tr -d '"' >> $GITHUB_OUTPUT + - name: Cancel workflow if version is not updated + if: steps.current_version.outputs.result == steps.latest_release.outputs.result + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh run cancel ${{ github.run_id }} + gh run watch ${{ github.run_id }} + - name: Checkout the repository + uses: actions/checkout@v4 + with: + token: ${{ secrets.IOS_GITHUB_TOKEN }} + submodules: 'recursive' + - name: Attach HEAD in submodule + working-directory: languages/swift/Rusaint + run: git switch main + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: 'aarch64-apple-ios, x86_64-apple-ios, aarch64-apple-ios-sim' + - name: Retrieve cache + uses: Leafwing-Studios/cargo-cache@v2 + - name: Install the Apple certificate + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.IOS_BUILD_CERTIFICATE_BASE64 }} + P12_PASSWORD: ${{ secrets.IOS_P12_PASSWORD }} + KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }} + run: | + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db + + # import certificate from secrets + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + - name: Build native library + env: + IPHONEOS_DEPLOYMENT_TARGET: 14.0 + RUSTFLAGS: '-C link-arg=-Wl,-application_extension' + run: | + mkdir $RUNNER_TEMP/target + CARGO_TARGET_DIR=$RUNNER_TEMP/target + cargo build --package rusaint-ffi --target aarch64-apple-ios-sim --release + cargo build --package rusaint-ffi --target aarch64-apple-ios --release + cargo build --package rusaint-ffi --target x86_64-apple-ios --release + - name: Create universal libraries for simulator + run: | + mkdir -p $RUNNER_TEMP/target/universal-ios-sim/release + lipo -create \ + $RUNNER_TEMP/target/aarch64-apple-ios-sim/release/librusaint_ffi.a \ + $RUNNER_TEMP/target/x86_64-apple-ios/release/librusaint_ffi.a \ + -output $RUNNER_TEMP/target/universal-ios-sim/release/librusaint_ffi.a + - name: Generate swift bindings + run: | + cargo run -p uniffi-bindgen generate \ + $RUNNER_TEMP/target/aarch64-apple-ios/release/librusaint_ffi.dylib \ + --library \ + --language swift \ + --no-format \ + --out-dir $RUNNER_TEMP/bindings + - name: Move generated swift bindgs + run: mv $RUNNER_TEMP/bindings/*.swift ./languages/swift/Rusaint/Sources/Rusaint/ + - name: Massage the generated files to fit xcframework + run: | + mkdir $RUNNER_TEMP/Headers + mv $RUNNER_TEMP/bindings/*.h $RUNNER_TEMP/Headers/ + cat $RUNNER_TEMP/bindings/*.modulemap > $RUNNER_TEMP/Headers/module.modulemap + - name: Create xcframework + run: | + rm -r ./languages/swift/Rusaint/Artifacts/RusaintFFI.xcframework + xcodebuild -create-xcframework \ + -library $RUNNER_TEMP/target/aarch64-apple-ios/release/librusaint_ffi.a \ + -headers $RUNNER_TEMP/Headers \ + -library $RUNNER_TEMP/target/universal-ios-sim/release/librusaint_ffi.a \ + -headers $RUNNER_TEMP/Headers \ + -output ./languages/swift/Rusaint/Artifacts/RusaintFFI.xcframework + - name: Sign xcframework + env: + KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }} + run: | + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $RUNNER_TEMP/signing.keychain-db + codesign --timestam-p -s "Apple Development" ./languages/swift/Rusaint/Artifacts/RusaintFFI.xcframework + - name: Push to submodule + working-directory: languages/swift/Rusaint + run: | + git config user.name "GitHub Actions" + git config user.email "" + git add . + git commit -m "release: ${{ steps.current_version.outputs.result }}" + git push + - name: Commit submodule in main repository + run: | + git config user.name "GitHub Actions" + git config user.email "" + git add languages/swift/Rusaint + git commit -m "release(ios): ${{ steps.current_version.outputs.result }}" + git push + - name: Create release + run: | + curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.IOS_GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/EATSTEAK/rusaint-ios/releases \ + -d '{"tag_name":"${{ steps.current_version.outputs.result }}","name":"${{ steps.current_version.outputs.result }}"}' \ No newline at end of file From bb1302998be43d2cdb0bd9a81a2544c000ae533c Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 15:58:14 +0900 Subject: [PATCH 15/18] ci: run release workflows if version in `Cargo.toml` changed --- .github/workflows/release.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b123d40..5ee101a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,35 @@ jobs: build: runs-on: ubuntu-latest steps: + - name: Checkout Cargo.toml to check version + uses: actions/checkout@v4 + with: + token: ${{ secrets.IOS_GITHUB_TOKEN }} + sparse-checkout: | + Cargo.toml + sparse-checkout-cone-mode: false + - name: Get rusaint version + id: current_version + uses: mikefarah/yq@v4 + with: + cmd: yq '.workspace.package.version | "v" + .' Cargo.toml + - name: Fetch latest release tag + id: latest_release + run: | + curl -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.IOS_GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/EATSTEAK/rusaint/releases \ + | jq '.[0].tag_name | "result=" + .' \ + | tr -d '"' >> $GITHUB_OUTPUT + - name: Cancel workflow if version is not updated + if: steps.current_version.outputs.result == steps.latest_release.outputs.result + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh run cancel ${{ github.run_id }} + gh run watch ${{ github.run_id }} - name: Checkout uses: actions/checkout@v4 - name: Setup Rust From ae9e83638bb1cfed9c45719469e6569c816fc3a0 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 16:14:49 +0900 Subject: [PATCH 16/18] ci: rename job name in workflows --- .github/workflows/dry-run.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/release-ios.yml | 2 +- .github/workflows/release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index b4b1192..eb99145 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -6,7 +6,7 @@ on: env: CARGO_TERM_COLOR: always jobs: - build: + dry-run: runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 286ec07..84e016f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -5,7 +5,7 @@ on: pull_request: branches: [ "main", "dev" ] jobs: - build: + lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release-ios.yml b/.github/workflows/release-ios.yml index 5030276..8001bca 100644 --- a/.github/workflows/release-ios.yml +++ b/.github/workflows/release-ios.yml @@ -9,7 +9,7 @@ on: permissions: actions: write jobs: - release: + release-ios: runs-on: macos-latest steps: - name: Checkout Cargo.toml to check version diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ee101a..975bcbc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ on: env: CARGO_TERM_COLOR: always jobs: - build: + release: runs-on: ubuntu-latest steps: - name: Checkout Cargo.toml to check version From cd626e1ea620bd9066ec4e32b80f1fb8482ba631 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 16:17:03 +0900 Subject: [PATCH 17/18] ci: make `IPHONE_DEPLOYMENT_TARGET` configurable --- .github/workflows/release-ios.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-ios.yml b/.github/workflows/release-ios.yml index 8001bca..5792db8 100644 --- a/.github/workflows/release-ios.yml +++ b/.github/workflows/release-ios.yml @@ -79,7 +79,7 @@ jobs: security list-keychain -d user -s $KEYCHAIN_PATH - name: Build native library env: - IPHONEOS_DEPLOYMENT_TARGET: 14.0 + IPHONEOS_DEPLOYMENT_TARGET: ${{ vars.IOS_DEPLOYMENT_TARGET || '14.0' }} RUSTFLAGS: '-C link-arg=-Wl,-application_extension' run: | mkdir $RUNNER_TEMP/target From e6bc40a665485736b9c788eb21a15c07150e5ac3 Mon Sep 17 00:00:00 2001 From: Hyomin Koo Date: Sat, 21 Dec 2024 16:36:36 +0900 Subject: [PATCH 18/18] ci: fix dry-run workflow and concurrency setup --- .github/workflows/build_test.yml | 2 +- .github/workflows/dry-run.yml | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 034e8c5..69b4bad 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -3,7 +3,7 @@ name: Build & Test on: workflow_dispatch: pull_request: - branches: [ "main", "dev" ] + branches: [ "dev" ] schedule: - cron: "23 3 * * *" env: diff --git a/.github/workflows/dry-run.yml b/.github/workflows/dry-run.yml index eb99145..6a0858e 100644 --- a/.github/workflows/dry-run.yml +++ b/.github/workflows/dry-run.yml @@ -8,6 +8,15 @@ env: jobs: dry-run: runs-on: ubuntu-latest + environment: testing + concurrency: + group: testing + cancel-in-progress: true + env: + SSO_ID: ${{ vars.SSO_ID }} + SSO_PASSWORD: ${{ secrets.SSO_PASSWORD }} + TARGET_YEAR: ${{ vars.TARGET_YEAR }} + TARGET_SEMESTER: ${{ vars.TARGET_SEMESTER }} steps: - name: Checkout uses: actions/checkout@v4