From e2df9aed4f1164e3c4aa0822750f202b9b08a006 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 20:57:19 -0700 Subject: [PATCH 1/9] Update GitHub actions for Rust --- .github/dependabot.yml | 20 ++++++++++ .github/workflows/build.yml | 65 +++++++++++++++++++----------- .github/workflows/lint.yml | 75 +++++++++++++++++++++++++++++++---- .github/workflows/sources.yml | 39 ++++++++++++++++++ 4 files changed, 169 insertions(+), 30 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/sources.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..a1d5890ab --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,20 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + open-pull-requests-limit: 15 + schedule: + interval: "weekly" + allow: + # Allow both direct and indirect updates for all packages + - dependency-type: "all" + groups: + minor-patch: + update-types: + - "minor" + - "patch" + + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44c915bca..a09f4e66b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,42 +1,61 @@ name: CI -on: [pull_request] +on: + push: + branches: ["main"] + paths: + - "*.json" + pull_request: + # branches: ["main"] + paths: + - "*.json" + types: + - opened + - reopened + - synchronize -jobs: - build: - runs-on: ubuntu-latest - container: - image: elementary/docker:unstable - steps: - - uses: actions/checkout@v1 - - name: Install Dependencies - run: | - apt update - apt install -y libarchive-dev valac meson appstream-util xvfb at-spi2-core git build-essential autoconf autoconf-archive autopoint automake pkg-config libtool m4 autoconf-archive gtk-doc-tools libxml2-utils gobject-introspection libgirepository1.0-dev libglib2.0-dev libjson-glib-dev gettext libcairo2-dev libgtk-3-dev - - name: Build - run: | - meson build - ninja -C build - ninja -C build install +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true +jobs: flatpak: name: Flatpak runs-on: ubuntu-latest + strategy: + matrix: + arch: [x86_64, aarch64] + # Don't fail the whole workflow if one architecture fails + fail-fast: false + container: - image: ghcr.io/elementary/flatpak-platform/runtime:6 + image: ghcr.io/elementary/flatpak-platform/runtime:7.3-${{ matrix.arch }} options: --privileged steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 + + - name: Install Rust SDK extension + run: | + flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + flatpak install -y --arch=${{matrix.arch}} org.freedesktop.Sdk.Extension.rust-stable//23.08 + + - name: Set up QEMU for aarch64 emulation + if: ${{ matrix.arch != 'x86_64' }} + uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 - name: Build - uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v3 + uses: flatpak/flatpak-github-actions/flatpak-builder@v6 with: - bundle: akira-dev.flatpak - manifest-path: com.github.akiraux.akira.yml - run-tests: true + bundle: app.flatpak + manifest-path: io.github.davidmhewitt.ElementaryRustExample.json + run-tests: ${{ matrix.arch == 'x86_64' }} repository-name: appcenter repository-url: https://flatpak.elementary.io/repo.flatpakrepo cache-key: "flatpak-builder-${{ github.sha }}" + branch: daily + arch: ${{ matrix.arch }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0985d9046..33662540f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,19 +2,80 @@ name: "CI: Lint" on: push: - branches: - - "master" + branches: ["main"] pull_request: + # branches: ["main"] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true + +env: + CARGO_TERM_COLOR: always jobs: - lint: + build: + runs-on: ubuntu-latest + container: + image: ghcr.io/elementary/docker:stable + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + run: | + apt-get update && apt-get install -y curl xvfb + - name: Install stable rust + run: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + - uses: actions/cache@v4 + with: + path: | + ./builddir + key: rust-${{ runner.os }}-${{ hashFiles('Cargo.lock') }} + restore-keys: | + rust-${{ runner.os }} + - name: Build + run: | + meson setup builddir + meson compile -C builddir + - name: Run tests + run: xvfb-run --auto-servernum meson test --print-errorlogs -C builddir + + format: runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install stable rust + run: | + rustup default stable + rustup set profile default + rustup update + - name: Touch empty config file + run: | + echo "" >> src/config.rs + - name: Run cargo fmt + run: | + cargo fmt --all -- --check + + clippy: + runs-on: ubuntu-latest container: - image: valalang/lint + image: ghcr.io/elementary/docker:stable steps: - - uses: actions/checkout@v1 - - name: Lint - run: io.elementary.vala-lint -d . + - uses: actions/checkout@v4 + - name: Install dependencies + run: | + apt-get update && apt-get install -y curl + - name: Install stable rust + run: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + echo "$HOME/.cargo/bin" >> $GITHUB_PATH + - name: Generate config.rs + run: | + meson setup builddir + - name: Run cargo clippy + run: | + cargo clippy -- -D warnings diff --git a/.github/workflows/sources.yml b/.github/workflows/sources.yml new file mode 100644 index 000000000..d33943eda --- /dev/null +++ b/.github/workflows/sources.yml @@ -0,0 +1,39 @@ +name: Update cargo sources + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +on: + push: + branches: ["main"] + paths: + - "Cargo.lock" + +permissions: + contents: write + pull-requests: write + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + path: repo + + - uses: actions/checkout@v4 + with: + repository: flatpak/flatpak-builder-tools + path: tools + + - name: Update modules + run: | + sudo apt-get install -y python3-toml python3-aiohttp + python3 tools/cargo/flatpak-cargo-generator.py -o repo/cargo-sources.json repo/Cargo.lock + - uses: peter-evans/create-pull-request@v6 + with: + path: repo + commit-message: Automated update of cargo-sources.json + title: Automated update of cargo-sources.json From 64ed9057473b531bdde5e2cc0752b37062375da3 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:00:45 -0700 Subject: [PATCH 2/9] Update CI action names --- .github/PULL_REQUEST_TEMPLATE.md | 17 +++++++++++------ .github/workflows/build.yml | 2 +- .github/workflows/sources.yml | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d162bd255..03ef9dfb7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,25 +3,30 @@ - + ## Summary / How this PR fixes the problem? + ## Steps to Test - -## Screenshots + + +## Screenshots + ## Known Issues / Things To Do + ## This PR fixes/implements the following **bugs/features**: - -- Fixes # -- Fixes # + + +- fixes # +- fixes # diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a09f4e66b..f1a8d6087 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: CI +name: "CI: build" on: push: diff --git a/.github/workflows/sources.yml b/.github/workflows/sources.yml index d33943eda..f54905222 100644 --- a/.github/workflows/sources.yml +++ b/.github/workflows/sources.yml @@ -1,4 +1,4 @@ -name: Update cargo sources +name: "CI: Cargo sources" concurrency: group: ${{ github.workflow }} From 45bfe9d601a7ef5e5744ec845a52db1e61a2d474 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:10:59 -0700 Subject: [PATCH 3/9] Fix Rust fmt and clippy warnings --- src/config.rs | 4 ++++ src/config.rs.in | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/config.rs b/src/config.rs index e4de2d31d..00aeffcf5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,9 @@ pub static APP_ID: &str = "com.github.akiraux.akira"; +#[allow(dead_code)] pub static SLASHED_APP_ID: &str = "/com/github/akiraux/akira/"; +#[allow(dead_code)] pub static GETTEXT_PACKAGE: &str = "com.github.akiraux.akira"; +#[allow(dead_code)] pub static LOCALEDIR: &str = "/usr/local/share/locale"; +#[allow(dead_code)] pub static PKGDATADIR: &str = "/usr/local/share/com.github.akiraux.akira"; diff --git a/src/config.rs.in b/src/config.rs.in index 336fe9037..cb3f7266e 100644 --- a/src/config.rs.in +++ b/src/config.rs.in @@ -1,5 +1,9 @@ pub static APP_ID: &str = @APP_ID@; +#[allow(dead_code)] pub static SLASHED_APP_ID: &str = @SLASHED_APP_ID@; +#[allow(dead_code)] pub static GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; +#[allow(dead_code)] pub static LOCALEDIR: &str = @LOCALEDIR@; +#[allow(dead_code)] pub static PKGDATADIR: &str = @PKGDATADIR@; From a976ab25d25ad33832754e26c3a96212a36797f3 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:14:29 -0700 Subject: [PATCH 4/9] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 899182c02..10ce2a650 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ .snapcraft .vscode -src/config.vala +src/config.rs build/ builddir/ _build/ From 6b22c58bc8167669bf4e7b2f9fccd4e8ad02ba0c Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:16:24 -0700 Subject: [PATCH 5/9] Remove the auto generated config file --- src/config.rs | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/config.rs diff --git a/src/config.rs b/src/config.rs deleted file mode 100644 index 00aeffcf5..000000000 --- a/src/config.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub static APP_ID: &str = "com.github.akiraux.akira"; -#[allow(dead_code)] -pub static SLASHED_APP_ID: &str = "/com/github/akiraux/akira/"; -#[allow(dead_code)] -pub static GETTEXT_PACKAGE: &str = "com.github.akiraux.akira"; -#[allow(dead_code)] -pub static LOCALEDIR: &str = "/usr/local/share/locale"; -#[allow(dead_code)] -pub static PKGDATADIR: &str = "/usr/local/share/com.github.akiraux.akira"; From d9f05ec383ac77227b652d38b71946c0a3dd205c Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:23:07 -0700 Subject: [PATCH 6/9] Install missing build dependency --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 33662540f..767d76a2b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v4 - name: Install dependencies run: | - apt-get update && apt-get install -y curl xvfb + apt-get update && apt-get install -y curl xvfb file - name: Install stable rust run: | curl https://sh.rustup.rs -sSf | sh -s -- -y From 50b8e58f29b02d15879cbe63cbd64f25e2240e0b Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 21:37:50 -0700 Subject: [PATCH 7/9] Add a sample test boilerplate --- .github/workflows/build.yml | 2 +- src/window.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1a8d6087..34a0b155c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ on: paths: - "*.json" pull_request: - # branches: ["main"] + branches: ["main"] paths: - "*.json" types: diff --git a/src/window.rs b/src/window.rs index 159305897..149325797 100644 --- a/src/window.rs +++ b/src/window.rs @@ -133,3 +133,12 @@ impl AppWindow { } } } + +#[cfg(test)] +mod test { + #[gtk::test] + fn test_main_window() { + let success: bool = true; + assert!(success); + } +} From 260d241ac8e21dd467c60a80932b643422002e93 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 22:09:11 -0700 Subject: [PATCH 8/9] Consume gettext --- .github/workflows/lint.yml | 3 +- src/application.rs | 116 +++++++++++++++++++++++++++++++++++++ src/main.rs | 33 ++++++----- 3 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 src/application.rs diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 767d76a2b..1812ce14a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,10 +1,9 @@ -name: "CI: Lint" +name: "CI" on: push: branches: ["main"] pull_request: - # branches: ["main"] concurrency: group: ${{ github.workflow }}-${{ github.event.number }} diff --git a/src/application.rs b/src/application.rs new file mode 100644 index 000000000..fa07492ce --- /dev/null +++ b/src/application.rs @@ -0,0 +1,116 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * Akira is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Akira. If not, see . + */ +use gtk::prelude::*; +use gtk::subclass::prelude::*; +use gtk::{gio, glib}; + +use crate::AppWindow; + +mod imp { + use granite::prelude::SettingsExt; + use gtk::glib::clone; + + use crate::config::SLASHED_APP_ID; + + use super::*; + + #[derive(Debug, Default)] + pub struct App {} + + #[glib::object_subclass] + impl ObjectSubclass for App { + const NAME: &'static str = "App"; + type Type = super::App; + type ParentType = gtk::Application; + } + + impl ObjectImpl for App { + fn constructed(&self) { + self.parent_constructed(); + let obj = self.obj(); + obj.setup_gactions(); + obj.set_accels_for_action("app.quit", &["q"]); + } + } + + impl ApplicationImpl for App { + fn activate(&self) { + let application = self.obj(); + // Get the current window or create one if necessary + let window = if let Some(window) = application.active_window() { + window + } else { + let window = AppWindow::new(&*application); + window.upcast() + }; + + window.present(); + } + + fn startup(&self) { + self.parent_startup(); + + granite::init(); + + let display = gtk::gdk::Display::default().expect("Couldn't get GDK display"); + gtk::IconTheme::for_display(&display).add_resource_path(SLASHED_APP_ID); + + let gtk_settings = + gtk::Settings::default().expect("Unable to get the GtkSettings object"); + let granite_settings = + granite::Settings::default().expect("Unable to get the Granite settings object"); + gtk_settings.set_gtk_application_prefer_dark_theme( + granite_settings.prefers_color_scheme() == granite::SettingsColorScheme::Dark, + ); + + granite_settings.connect_prefers_color_scheme_notify(clone!( + #[weak] + gtk_settings, + move |granite_settings| { + gtk_settings.set_gtk_application_prefer_dark_theme( + granite_settings.prefers_color_scheme() + == granite::SettingsColorScheme::Dark, + ); + } + )); + } + } + + impl GtkApplicationImpl for App {} +} + +glib::wrapper! { + pub struct App(ObjectSubclass) + @extends gio::Application, gtk::Application, + @implements gio::ActionGroup, gio::ActionMap; +} + +impl App { + pub fn new(application_id: &str, flags: &gio::ApplicationFlags) -> Self { + glib::Object::builder() + .property("application-id", application_id) + .property("flags", flags) + .build() + } + + fn setup_gactions(&self) { + let quit_action = gio::ActionEntry::builder("quit") + .activate(move |app: &Self, _, _| app.quit()) + .build(); + self.add_action_entries([quit_action]); + } +} diff --git a/src/main.rs b/src/main.rs index 9670dd5b2..b3c27b5ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,30 +14,31 @@ * You should have received a copy of the GNU General Public License along with * Akira. If not, see . */ +mod application; mod config; mod window; -use config::APP_ID; +use config::{APP_ID, GETTEXT_PACKAGE, LOCALEDIR}; +use gettextrs::{bind_textdomain_codeset, bindtextdomain, textdomain}; +use gtk::gio; use gtk::prelude::*; -use gtk::{glib, Application}; +use self::application::App; use self::window::AppWindow; -fn main() -> glib::ExitCode { - // Create a new application - let app = Application::builder().application_id(APP_ID).build(); +fn main() { + // Set up gettext translations + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR).expect("Unable to bind the text domain"); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8") + .expect("Unable to set the text domain encoding"); + textdomain(GETTEXT_PACKAGE).expect("Unable to switch to the text domain"); - // Connect to "activate" signal of `app` - app.connect_activate(build_ui); + // TODO: Load resources once we need to consume custom SVGs + // let resources = gio::Resource::load(PKGDATADIR.to_owned() + "/" + APP_ID + ".gresource") + // .expect("Could not load resources"); + // gio::resources_register(&resources); - // Run the application - app.run() -} - -fn build_ui(app: &Application) { - // Create a window and set the title - let window = AppWindow::new(app); + let app = App::new(APP_ID, &gio::ApplicationFlags::empty()); - // Present window - window.present(); + std::process::exit(app.run().value()); } From 2bbfed3c168f1858d613af797002036f34f7fff3 Mon Sep 17 00:00:00 2001 From: Alecaddd Date: Thu, 19 Sep 2024 22:15:30 -0700 Subject: [PATCH 9/9] Set a fixed gettext-rs version --- Cargo.toml | 2 +- src/config.rs.in | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bafb8343e..fe823d680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -gettext-rs = "0.7.1" +gettext-rs = { version = "0.7", features = ["gettext-system"] } granite = { version = "1.1", package = "granite-rs", features = ["v7_2"] } gtk = { version = "0.9.1", package = "gtk4" } once_cell = "1.19.0" diff --git a/src/config.rs.in b/src/config.rs.in index cb3f7266e..ff1c2dea3 100644 --- a/src/config.rs.in +++ b/src/config.rs.in @@ -1,9 +1,6 @@ pub static APP_ID: &str = @APP_ID@; -#[allow(dead_code)] pub static SLASHED_APP_ID: &str = @SLASHED_APP_ID@; -#[allow(dead_code)] pub static GETTEXT_PACKAGE: &str = @GETTEXT_PACKAGE@; -#[allow(dead_code)] pub static LOCALEDIR: &str = @LOCALEDIR@; #[allow(dead_code)] pub static PKGDATADIR: &str = @PKGDATADIR@;