diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..5333707 --- /dev/null +++ b/.envrc @@ -0,0 +1,4 @@ +if ! has nix_direnv_version || ! nix_direnv_version 2.2.1; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.2.1/direnvrc" "sha256-zelF0vLbEl5uaqrfIzbgNzJWGmLzCmYAkInj/LNxvKs=" +fi +use flake . diff --git a/.forgejo/workflows/renovate-config-validation.yaml b/.forgejo/workflows/renovate-config-validation.yaml new file mode 100644 index 0000000..bb1dce6 --- /dev/null +++ b/.forgejo/workflows/renovate-config-validation.yaml @@ -0,0 +1,15 @@ +--- +name: Checking Renovate configuration + +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Validate Renovate configuration + uses: suzuki-shunsuke/github-action-renovate-config-validator@v1.1.1 +... diff --git a/.forgejo/workflows/rust.yml b/.forgejo/workflows/rust.yml new file mode 100644 index 0000000..0dba416 --- /dev/null +++ b/.forgejo/workflows/rust.yml @@ -0,0 +1,149 @@ +--- +# yamllint disable rule:line-length + +name: Build and test + +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + tests: + name: Tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache Rust toolchain and dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo + ~/.rustup + target + key: ${{ runner.os }}-rustup-cargo-test-${{ hashFiles('rust-toolchain.toml', 'rust-toolchain') || 'stable' }} + restore-keys: | + ${{ runner.os }}-rustup-cargo-test- + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + components: rustfmt + override: true + - name: Show versions + run: | + rustc --version + cargo --version + - name: Check formatting + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --check + - name: Run tests + uses: actions-rs/cargo@v1 + with: + command: test + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache Rust toolchain and dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo + ~/.rustup + target + key: ${{ runner.os }}-rustup-cargo-clippy-${{ hashFiles('rust-toolchain.toml', 'rust-toolchain') || 'stable' }} + restore-keys: | + ${{ runner.os }}-rustup-cargo-clippy- + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + components: clippy + override: true + - name: Show versions + run: | + rustc --version + cargo --version + - name: Clippy check + uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings + + build-amd64: + name: Build AMD64 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache Rust toolchain and dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo + ~/.rustup + target + key: ${{ runner.os }}-rustup-cargo-build-${{ hashFiles('rust-toolchain.toml', 'rust-toolchain') || 'stable' }} + restore-keys: | + ${{ runner.os }}-rustup-cargo-build- + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Show versions + run: | + rustc --version + cargo --version + - name: Build release binary + uses: actions-rs/cargo@v1 + with: + command: build + args: --release --all-features + - name: Upload binary artifact + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: cbz2pdf-linux-amd64 + path: target/release/cbz2pdf + + rustdoc: + name: Generate Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache Rust toolchain and dependencies + uses: actions/cache@v4 + with: + path: | + ~/.cargo + ~/.rustup + target + key: ${{ runner.os }}-rustup-cargo-doc-${{ hashFiles('rust-toolchain.toml', 'rust-toolchain') || 'stable' }} + restore-keys: | + ${{ runner.os }}-rustup-cargo-doc- + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Show versions + run: | + rustc --version + cargo --version + - name: Generate documentation + uses: actions-rs/cargo@v1 + with: + command: doc + - name: Compress documentation + run: tar -czf rustdoc.tar.gz -C target doc + - name: Upload documentation artifact + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: rustdoc + path: rustdoc.tar.gz +... diff --git a/.forgejo/workflows/yamllint.yaml b/.forgejo/workflows/yamllint.yaml new file mode 100644 index 0000000..1b5cb26 --- /dev/null +++ b/.forgejo/workflows/yamllint.yaml @@ -0,0 +1,18 @@ +--- +name: Checking yaml + +on: # yamllint disable-line rule:truthy + pull_request: + +jobs: + yamllint: + name: Run yamllint + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Run YAML linter + uses: bewuethr/yamllint-action@v1 + with: + config-file: .yamllint.yaml +... diff --git a/.gitignore b/.gitignore index ea8c4bf..3f4b997 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ +.direnv/ +.idea/ /target +.rust-toolchain +.pre-commit-config.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index b004b0e..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,61 +0,0 @@ ---- -stages: - - test - - build - - publish - - -default: - -tests: - stage: test - image: rust - before_script: - - rustc --version - - cargo --version - - rustup component add rustfmt - script: - - cargo fmt --check - - cargo test - -build:amd64: - stage: build - image: rust - before_script: - - rustc --version - - cargo --version - script: - - cargo build --release - artifacts: - paths: - - target/release/cbz2pdf - -rustdoc: - stage: build - image: rust - before_script: - - rustc --version - - cargo --version - script: - - cargo doc - artifacts: - paths: - - target/doc - -pages: - stage: publish - image: alpine - dependencies: - - build:amd64 - - rustdoc - script: - - mkdir -p public - - mv target/doc public/doc - - mv target/release/cbz2pdf public/cbz2pdf-amd64 - artifacts: - paths: - - public - only: - - main -... - diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..79bc82f --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,30 @@ +--- +ignore: | + .platformio + secrets.yaml + +rules: + braces: enable + brackets: enable + colons: enable + commas: enable + comments: enable + comments-indentation: enable + document-end: enable + document-start: enable + empty-lines: + max: 1 + empty-values: disable + hyphens: enable + indentation: enable + key-duplicates: enable + key-ordering: disable + line-length: + max: 100 + new-line-at-end-of-file: enable + new-lines: enable + octal-values: enable + quoted-strings: disable + trailing-spaces: enable + truthy: enable +... diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..d818c70 --- /dev/null +++ b/flake.lock @@ -0,0 +1,121 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1755615617, + "narHash": "sha256-HMwfAJBdrr8wXAkbGhtcby1zGFvs+StOp19xNsbqdOg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "20075955deac2583bb12f07151c2df830ef346b4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1755960406, + "narHash": "sha256-RF7j6C1TmSTK9tYWO6CdEMtg6XZaUKcvZwOCD2SICZs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "e891a93b193fcaf2fc8012d890dc7f0befe86ec2", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "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", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..d3dd6f0 --- /dev/null +++ b/flake.nix @@ -0,0 +1,39 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + pre-commit-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { self + , nixpkgs + , flake-utils + , ... + }@inputs: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + }; + # Place all toolchain components in a single directory for IntelliJ + rust-toolchain = pkgs.symlinkJoin { + name = "rust-toolchain"; + paths = with pkgs; [ + rustc + cargo + rustPlatform.rustcSrc + ] ++ lib.optionals stdenv.isDarwin [ + libiconv + ]; + }; + in + { + checks = import ./nix/git-hooks.nix { inherit inputs pkgs; }; + devShells = import ./nix/shell.nix { inherit pkgs rust-toolchain self; }; + formatter = pkgs.nixpkgs-fmt; + }); +} diff --git a/nix/git-hooks.nix b/nix/git-hooks.nix new file mode 100644 index 0000000..355da46 --- /dev/null +++ b/nix/git-hooks.nix @@ -0,0 +1,65 @@ +{ inputs, pkgs, ... }: +let + conventional-commit = pkgs.callPackage ./pkgs/conventional-pre-commit.nix { }; +in +{ + pre-commit-check = inputs.pre-commit-hooks.lib.${pkgs.system}.run { + src = ./..; + hooks = { + # TOML + check-toml.enable = true; + + # YAML + check-yaml.enable = true; + + # Nix + deadnix.enable = true; + flake-checker.enable = true; + nixpkgs-fmt.enable = true; + statix.enable = true; + + # Rust + clippy = { + enable = true; + settings = { + denyWarnings = true; + }; + extraPackages = with pkgs; [ + openssl + pkg-config + ]; + }; + rustfmt.enable = true; + cargo-check = { + enable = true; + extraPackages = with pkgs; [ + pkg-config + openssl + ]; + }; + + # Git + no-commit-to-branch = { + enable = true; + settings = { + branch = [ "main" ]; + }; + }; + conventional-commit = { + enable = true; + name = "conventional-commit"; + description = "A pre-commit hook that checks commit messages for Conventional Commits formatting"; + package = conventional-commit; + entry = "${conventional-commit}/bin/conventional-pre-commit"; + args = [ "--strict" "feat" "fix" "chore" "revert" "style" "docs" "build" "refactor" "test" "ci" "perf" ]; + stages = [ "commit-msg" ]; + }; + }; + + settings = { + rust.check.cargoDeps = pkgs.rustPlatform.importCargoLock { + lockFile = ../Cargo.lock; + }; + }; + }; +} diff --git a/nix/pkgs/conventional-pre-commit.nix b/nix/pkgs/conventional-pre-commit.nix new file mode 100644 index 0000000..dbeb136 --- /dev/null +++ b/nix/pkgs/conventional-pre-commit.nix @@ -0,0 +1,20 @@ +{ python3Packages, fetchPypi, ... }: + +python3Packages.buildPythonApplication rec { + pname = "conventional_pre_commit"; + version = "4.2.0"; + + src = fetchPypi { + inherit pname version; + hash = "sha256-a1ooZzOMWKHRTTAN5otWwXt8hAO7EiFV84Y5pCPSH/E="; + }; + + doCheck = false; + pyproject = true; + + build-system = with python3Packages; [ + setuptools + setuptools-scm + wheel + ]; +} diff --git a/nix/shell.nix b/nix/shell.nix new file mode 100644 index 0000000..549c164 --- /dev/null +++ b/nix/shell.nix @@ -0,0 +1,36 @@ +{ pkgs, rust-toolchain, self, ... }: + +{ + default = pkgs.mkShell { + name = "cbz2pdf"; + buildInputs = with pkgs; [ + cargo + cargo-edit + cargo-insta + cargo-machete + cargo-release + cargo-sort + git-cliff + openssl + pkg-config + rustc + rust-toolchain + ] ++ lib.optionals stdenv.isDarwin [ + libiconv + ] ++ self.checks.${pkgs.system}.pre-commit-check.enabledPackages; + RUST_BACKTRACE = 1; + + # Copy rust-toolchain to project directory for easy use in IntelliJ + shellHook = '' + if [ -L ./.rust-toolchain ] && [ "$(readlink ./.rust-toolchain)" = "${rust-toolchain}" ]; then + echo "Rust toolchain symlink is already correct." + else + rm -f ./.rust-toolchain + ln -s ${rust-toolchain} ./.rust-toolchain + echo "Rust toolchain symlink updated." + fi + + ${self.checks.${pkgs.system}.pre-commit-check.shellHook} + ''; + }; +} diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..aa41364 --- /dev/null +++ b/renovate.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "assignees": ["kernald"], + "extends": [ + "config:recommended" + ] +}