diff --git a/.github/workflows/orca.yaml b/.github/workflows/orca.yaml index c19f39e..102406c 100644 --- a/.github/workflows/orca.yaml +++ b/.github/workflows/orca.yaml @@ -6,7 +6,6 @@ on: jobs: nix-build: runs-on: ubuntu-latest - # if: github.ref_name == 'main' steps: - name: Clone repository uses: actions/checkout@v3 @@ -15,6 +14,10 @@ jobs: - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main + - name: Check orca + working-directory: orca + run: nix flake check --log-format raw + - name: Build via nix working-directory: orca - run: nix build + run: nix build --log-format raw diff --git a/orca/default.nix b/orca/default.nix index 288dc2e..d63504f 100644 --- a/orca/default.nix +++ b/orca/default.nix @@ -1,32 +1,58 @@ -{ rustPlatform -, pkg-config +{ pkg-config , openssl , stdenv -, darwin -, lib +, callPackage , texlive , makeWrapper , nix-gitignore -, ibm-plex , buildFeatures ? [] +, crane +, system +, lib +, darwin }: let tex = import ./latex { inherit texlive; }; -in -rustPlatform.buildRustPackage { - inherit buildFeatures; - - pname = "ict-union-orca"; - version = "0.1.0"; src = nix-gitignore.gitignoreSource [] ./.; - cargoSha256 = "sha256-iW18bgQwXIT6jL+PW3UxELqUzDJLxldAwwJv2FudB4o="; + craneLib = crane.lib.${system}; + nativeBuildInputs = [ + openssl + pkg-config + ]; - nativeBuildInputs = [ pkg-config makeWrapper ]; + # Build *just* the cargo dependencies, so we can reuse + # all of that work (e.g. via cachix) when running in CI + cargoArtifacts = craneLib.buildDepsOnly { + inherit src nativeBuildInputs; + }; - buildInputs = [ openssl ] ++ lib.optionals stdenv.isDarwin [ - darwin.apple_sdk.frameworks.Security - ]; - postInstall = '' - wrapProgram "$out/bin/orca" --suffix PATH : "${tex}/bin" + # Run clippy (and deny all warnings) on the crate source, + # resuing the dependency artifacts (e.g. from build scripts or + # proc-macros) from above. + # + # Note that this is done as a separate derivation so it + # does not impact building just the crate by itself. + orca-clippy = craneLib.cargoClippy { + inherit cargoArtifacts src nativeBuildInputs; + cargoClippyExtraArgs = "-- --deny warnings"; + }; + + orca-fmt = craneLib.cargoFmt { + inherit src; + }; +in +rec { + orca = craneLib.buildPackage { + inherit cargoArtifacts src; + nativeBuildInputs = nativeBuildInputs ++ [ makeWrapper ]; + buildInputs = [ openssl ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + ]; + postInstall = '' + wrapProgram "$out/bin/orca" --suffix PATH : "${tex}/bin" ''; + }; + + inherit orca-clippy; + inherit orca-fmt; } diff --git a/orca/flake.lock b/orca/flake.lock index 6d7eb12..ad33cef 100644 --- a/orca/flake.lock +++ b/orca/flake.lock @@ -1,12 +1,35 @@ { "nodes": { + "crane": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1697840921, + "narHash": "sha256-zXHwu104SQOxogkMgg+w22c3+zI/FvK83TAkfLmeKw0=", + "owner": "ipetkov", + "repo": "crane", + "rev": "758ae442227103fa501276e8225609a11c99718e", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1676283394, - "narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -17,11 +40,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1678032814, - "narHash": "sha256-5Kp637MM8l/zd9LIwWTD59u4m1e1Lk0buiPT++Fo3E0=", + "lastModified": 1697882456, + "narHash": "sha256-VhmCnEsVGTOCbHBZbjuIuh58lU7OSNu5TyYnCqE/5uo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3ce09002488bf7103f5e4486ccfba5640c82ba6b", + "rev": "ca42fb99b88ddf55aa86729982b6041845566be6", "type": "github" }, "original": { @@ -32,9 +55,25 @@ }, "root": { "inputs": { + "crane": "crane", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/orca/flake.nix b/orca/flake.nix index 1534262..c8ec759 100644 --- a/orca/flake.nix +++ b/orca/flake.nix @@ -3,9 +3,11 @@ inputs = { nixpkgs.url = github:NixOS/nixpkgs; flake-utils.url = github:numtide/flake-utils; + crane.url = "github:ipetkov/crane"; + crane.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: + outputs = { self, nixpkgs, flake-utils, crane }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; @@ -18,9 +20,13 @@ openssl pkg-config ]; - in + + orcaPkgs = pkgs.callPackage ./default.nix { + inherit crane; + }; + in rec { - devShell = with pkgs; + devShells.default = with pkgs; mkShell { name = "ict-union-orca-dev-env"; inherit buildInputs; @@ -30,6 +36,11 @@ ''; OSFONTDIR = "${pkgs.ibm-plex}/share/fonts/opentype"; }; - defaultPackage = pkgs.callPackage ./default.nix {}; - }); + + defaultPackage = orcaPkgs.orca; + + checks = { + inherit (orcaPkgs) orca orca-clippy orca-fmt; + }; + }); } diff --git a/orca/src/api/applications/mod.rs b/orca/src/api/applications/mod.rs index f9ec473..f567efa 100644 --- a/orca/src/api/applications/mod.rs +++ b/orca/src/api/applications/mod.rs @@ -530,8 +530,12 @@ async fn hard_delete<'r>( .to_status() .assert_rejected()?; - query::dangerous_hard_delete_application_data(id).execute(&mut tx).await?; - query::dangerous_hard_delete_application(id).execute(&mut tx).await?; + query::dangerous_hard_delete_application_data(id) + .execute(&mut tx) + .await?; + query::dangerous_hard_delete_application(id) + .execute(&mut tx) + .await?; tx.commit().await?; diff --git a/orca/src/processing/mod.rs b/orca/src/processing/mod.rs index c11cf5a..4034051 100644 --- a/orca/src/processing/mod.rs +++ b/orca/src/processing/mod.rs @@ -136,7 +136,7 @@ async fn process( match command { NewRegistrationRequest(reg_id, signature) => { - process_new_registration(reg_id, signature, config, db_pool).await + process_new_registration(reg_id, signature, config, db_pool).await?; } ResentRegistrationEmail(reg_id) => { let application_details = query::query_registration(reg_id).fetch_one(db_pool).await?; @@ -145,7 +145,7 @@ async fn process( .fetch_one(db_pool) .await?; - send_verification_email(config, db_pool, &application_details, pdf_data).await + send_verification_email(config, db_pool, &application_details, pdf_data).await?; } RegistrationRequestVerified(reg_id) => { // We do this only if notification email is configured @@ -200,10 +200,10 @@ async fn process( send_email(config, message).await?; } - - Ok(()) } } + + Ok(()) } async fn send_email(config: &Config, message: Message) -> Result<(), ProcessingError> { @@ -231,8 +231,8 @@ async fn process_new_registration( .await?; // Query for detail information about member - // in theory we could also pass this in thee command - // but doing it this way means that all triggers, defaults etc are 100% applied to the data + // in theory we could also pass this in the command + // but doing it this way means that all triggers & defaults etc are 100% applied to the data let application_details = query::query_registration(reg_id).fetch_one(db_pool).await?; // Generate PDF @@ -256,6 +256,8 @@ async fn send_verification_email( application_details: &RegistrationDetails, pdf_data: Vec, ) -> Result<(), ProcessingError> { + info!("Send verification email to {}", application_details.email); + let token = application_details .confirmation_token .as_ref() @@ -395,6 +397,8 @@ async fn print_pdf( application_details: &RegistrationDetails, dir: &str, ) -> Result { + info!("Printing registration pdf at {dir}"); + // inline static files let form_tex = include_str!("../../latex/registration.tex"); let logo_png = include_bytes!("../../latex/logo.png"); @@ -424,9 +428,12 @@ async fn print_pdf( .stdout(Stdio::null()) .spawn()?; - // Await until the command completes + // Await until command completes + // There is a problem with tokio detecting the exist status of the process + // at least in cases where xelatex fails to find font in OSFONTDIR + // like similar to https://users.rust-lang.org/t/tokio-child-wait-never-returning/96657 let status = child.wait().await?; - info!("tex command exited successfully: {status}"); + info!("Tex command exited successfully: {status}"); Ok(format!("{dir}/registration.pdf")) }