diff --git a/.forgejo/workflows/check.yml b/.forgejo/workflows/check.yml index ee386bf..ab33bfa 100644 --- a/.forgejo/workflows/check.yml +++ b/.forgejo/workflows/check.yml @@ -3,12 +3,12 @@ jobs: check: runs-on: nixos steps: - - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://git.salame.cl/actions/checkout@v4 - run: nix --version - run: nix flake check --keep-going --verbose --print-build-logs build: runs-on: nixos steps: - - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://git.salame.cl/actions/checkout@v4 - run: nix --version - run: nix build --print-build-logs .# diff --git a/.forgejo/workflows/update.yml b/.forgejo/workflows/update.yml new file mode 100644 index 0000000..aad6c30 --- /dev/null +++ b/.forgejo/workflows/update.yml @@ -0,0 +1,62 @@ +on: + workflow_dispatch: + schedule: + # 03:42 on Saturdays + - cron: '42 3 * * 6' +env: + PR_TITLE: Weekly `cargo update` of dependencies + PR_MESSAGE: | + Automation to keep dependencies in `Cargo.lock` current. + + The following is the output from `cargo update`: + COMMIT_MESSAGE: "chore: cargo update \n\n" +jobs: + update-cargo: + runs-on: nixos + env: + BRANCH_NAME: cargo-update + steps: + - uses: https://git.salame.cl/actions/checkout@v4 + - run: nix --version + - run: nix run .#cargo-update + - name: craft PR body and commit message + run: | + set -euo pipefail + + echo "${COMMIT_MESSAGE}" > commit.txt + cat cargo_update.log >> commit.txt + + echo "${PR_MESSAGE}" > body.md + echo '```txt' >> body.md + cat cargo_update.log >> body.md + echo '```' >> body.md + - name: commit + run: | + set -euo pipefail + + git config user.name forgejo-actions + git config user.email forgejo-actions@salame.cl + git switch --force-create "$BRANCH_NAME" + git add ./Cargo.lock + DIFF="$(git diff --staged)" + if [[ "$DIFF" == "" ]]; then + echo >2 "Cargo.lock was not changed, bailing out and not making a PR" + exit 1 + fi + git commit --no-verify --file=commit.txt + - name: push + run: | + set -euo pipefail + git push --no-verify --force --set-upstream origin "$BRANCH_NAME" + - name: open new pull request + env: + # We have to use a Personal Access Token (PAT) here. + # PRs opened from a workflow using the standard `GITHUB_TOKEN` in GitHub Actions + # do not automatically trigger more workflows: + # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#using-the-github_token-in-a-workflow + # GITHUB_TOKEN: ${{ secrets.DEPS_UPDATER_GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + tea login add --name "forgejo-actions" --token "$GITHUB_TOKEN" + tea pr create --title "${PR_TITLE}" --description "$(cat body.md)" --repo "$GITHUB_REPOSITORY" diff --git a/default.nix b/default.nix index a374ee4..a3b6c80 100644 --- a/default.nix +++ b/default.nix @@ -1,7 +1,8 @@ { lib, rustPlatform, -}: let +}: +let readToml = path: builtins.fromTOML (builtins.readFile path); cargoToml = readToml ./Cargo.toml; pname = cargoToml.package.name; @@ -11,32 +12,34 @@ name = "${pname}-source"; # Adapted from # no need to pull in crane for just this - filter = orig_path: type: let - path = toString orig_path; - base = baseNameOf path; - parentDir = baseNameOf (dirOf path); - matchesSuffix = lib.any (suffix: lib.hasSuffix suffix base) [ - # Rust sources - ".rs" - # TOML files are often used to configure cargo based tools (e.g. .cargo/config.toml) - ".toml" - ]; - isCargoLock = base == "Cargo.lock"; - # .cargo/config.toml is captured above - isOldStyleCargoConfig = parentDir == ".cargo" && base == "config"; - in + filter = + orig_path: type: + let + path = toString orig_path; + base = baseNameOf path; + parentDir = baseNameOf (dirOf path); + matchesSuffix = lib.any (suffix: lib.hasSuffix suffix base) [ + # Rust sources + ".rs" + # TOML files are often used to configure cargo based tools (e.g. .cargo/config.toml) + ".toml" + ]; + isCargoLock = base == "Cargo.lock"; + # .cargo/config.toml is captured above + isOldStyleCargoConfig = parentDir == ".cargo" && base == "config"; + in type == "directory" || matchesSuffix || isCargoLock || isOldStyleCargoConfig; }; in - rustPlatform.buildRustPackage { - inherit pname version src; - cargoLock.lockFile = ./Cargo.lock; - useNextest = true; +rustPlatform.buildRustPackage { + inherit pname version src; + cargoLock.lockFile = ./Cargo.lock; + useNextest = true; - meta = { - inherit description; - license = lib.licenses.mit; - homepage = "https://github.com/jalil-salame/webnsupdate"; - mainProgram = "webnsupdate"; - }; - } + meta = { + inherit description; + license = lib.licenses.mit; + homepage = "https://github.com/jalil-salame/webnsupdate"; + mainProgram = "webnsupdate"; + }; +} diff --git a/flake.lock b/flake.lock index 9b7c6c4..5e655a0 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1725634671, - "narHash": "sha256-v3rIhsJBOMLR8e/RNWxr828tB+WywYIoajrZKFM+0Gg=", + "lastModified": 1727348695, + "narHash": "sha256-J+PeFKSDV+pHL7ukkfpVzCOO7mBSrrpJ3svwBFABbhI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c", + "rev": "1925c603f17fc89f4c8f6bf6f631a802ad85d784", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 530439b..5f271d0 100644 --- a/flake.nix +++ b/flake.nix @@ -5,59 +5,83 @@ systems.url = "github:nix-systems/default"; }; - outputs = { - self, - nixpkgs, - systems, - }: let - forEachSupportedSystem = nixpkgs.lib.genAttrs (import systems); - in { - checks = forEachSupportedSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; - inherit (nixpkgs) lib; - in { - fmtRust = pkgs.callPackage ./run-cmd.nix { - src = self; - name = "fmt-rust"; - extraNativeBuildInputs = [pkgs.rustfmt]; - cmd = "${lib.getExe pkgs.cargo} fmt --all --check --verbose"; - }; - fmtNix = pkgs.callPackage ./run-cmd.nix { - src = self; - name = "fmt-nix"; - cmd = "${lib.getExe pkgs.alejandra} --check ."; - }; - lintNix = pkgs.callPackage ./run-cmd.nix { - src = self; - name = "lint-nix"; - cmd = "${lib.getExe pkgs.statix} check ."; - }; - }); - formatter = forEachSupportedSystem (system: nixpkgs.legacyPackages.${system}.alejandra); + outputs = + { + self, + nixpkgs, + systems, + }: + let + forEachSupportedSystem = nixpkgs.lib.genAttrs (import systems); + in + { + checks = forEachSupportedSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + inherit (nixpkgs) lib; + in + { + fmtRust = pkgs.callPackage ./run-cmd.nix { + src = self; + name = "fmt-rust"; + extraNativeBuildInputs = [ pkgs.rustfmt ]; + cmd = "${lib.getExe pkgs.cargo} fmt --all --check --verbose"; + }; + fmtNix = pkgs.callPackage ./run-cmd.nix { + src = self; + name = "fmt-nix"; + cmd = "${lib.getExe self.formatter.${system}} --check ."; + }; + lintNix = pkgs.callPackage ./run-cmd.nix { + src = self; + name = "lint-nix"; + cmd = "${lib.getExe pkgs.statix} check ."; + }; + } + ); + formatter = forEachSupportedSystem (system: nixpkgs.legacyPackages.${system}.nixfmt-rfc-style); - packages = forEachSupportedSystem (system: let - webnsupdate = nixpkgs.legacyPackages.${system}.callPackage ./default.nix {}; - in { - inherit webnsupdate; - default = webnsupdate; - }); + packages = forEachSupportedSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + webnsupdate = pkgs.callPackage ./default.nix { }; + in + { + inherit webnsupdate; + default = webnsupdate; + cargo-update = pkgs.writeShellApplication { + name = "cargo-update-lockfile"; + runtimeInputs = with pkgs; [ + cargo + gnused + ]; + text = '' + CARGO_TERM_COLOR=never cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log + ''; + }; + } + ); - overlays.default = final: prev: { - webnsupdate = final.callPackage ./default.nix {}; + overlays.default = final: prev: { webnsupdate = final.callPackage ./default.nix { }; }; + + nixosModules.default = ./module.nix; + + devShells = forEachSupportedSystem ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + default = pkgs.mkShell { + packages = [ + pkgs.cargo-insta + pkgs.cargo-udeps + pkgs.mold + ]; + }; + } + ); }; - - nixosModules.default = ./module.nix; - - devShells = forEachSupportedSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; - in { - default = pkgs.mkShell { - packages = [ - pkgs.cargo-insta - pkgs.cargo-udeps - pkgs.mold - ]; - }; - }); - }; } diff --git a/module.nix b/module.nix index 2f3834d..203998f 100644 --- a/module.nix +++ b/module.nix @@ -3,13 +3,15 @@ pkgs, config, ... -}: let +}: +let cfg = config.services.webnsupdate; inherit (lib) mkOption mkEnableOption types; -in { +in +{ options.services.webnsupdate = mkOption { description = "An HTTP server for nsupdate."; - default = {}; + default = { }; type = types.submodule { options = { enable = mkEnableOption "webnsupdate"; @@ -18,8 +20,8 @@ in { Extra arguments to be passed to the webnsupdate server command. ''; type = types.listOf types.str; - default = []; - example = ["--ip-source"]; + default = [ ]; + example = [ "--ip-source" ]; }; bindIp = mkOption { description = '' @@ -102,47 +104,53 @@ in { }; }; - config = let - recordsFile = - if cfg.recordsFile != null - then cfg.recordsFile - else pkgs.writeText "webnsrecords" cfg.records; - args = lib.strings.escapeShellArgs ([ - "--records" - recordsFile - "--key-file" - cfg.keyFile - "--password-file" - cfg.passwordFile - "--address" - cfg.bindIp - "--port" - (builtins.toString cfg.bindPort) - "--ttl" - (builtins.toString cfg.ttl) - ] - ++ cfg.extraArgs); - cmd = "${lib.getExe pkgs.webnsupdate} ${args}"; - in + config = + let + recordsFile = + if cfg.recordsFile != null then cfg.recordsFile else pkgs.writeText "webnsrecords" cfg.records; + args = lib.strings.escapeShellArgs ( + [ + "--records" + recordsFile + "--key-file" + cfg.keyFile + "--password-file" + cfg.passwordFile + "--address" + cfg.bindIp + "--port" + (builtins.toString cfg.bindPort) + "--ttl" + (builtins.toString cfg.ttl) + ] + ++ cfg.extraArgs + ); + cmd = "${lib.getExe pkgs.webnsupdate} ${args}"; + in lib.mkIf cfg.enable { # warnings = # lib.optional (!config.services.bind.enable) "`webnsupdate` is expected to be used alongside `bind`. This is an unsopported configuration."; assertions = [ { - assertion = (cfg.records != null || cfg.recordsFile != null) && !(cfg.records != null && cfg.recordsFile != null); + assertion = + (cfg.records != null || cfg.recordsFile != null) + && !(cfg.records != null && cfg.recordsFile != null); message = "Exactly one of `services.webnsupdate.records` and `services.webnsupdate.recordsFile` must be set."; } ]; systemd.services.webnsupdate = { description = "Web interface for nsupdate."; - wantedBy = ["multi-user.target"]; - after = ["network.target" "bind.service"]; + wantedBy = [ "multi-user.target" ]; + after = [ + "network.target" + "bind.service" + ]; preStart = "${cmd} verify"; - path = [pkgs.dig]; + path = [ pkgs.dig ]; startLimitIntervalSec = 60; serviceConfig = { - ExecStart = [cmd]; + ExecStart = [ cmd ]; Type = "exec"; Restart = "on-failure"; RestartSec = "10s"; diff --git a/run-cmd.nix b/run-cmd.nix index e483e7b..02bbe9f 100644 --- a/run-cmd.nix +++ b/run-cmd.nix @@ -3,8 +3,8 @@ src, name, cmd, - extraBuildInputs ? [], - extraNativeBuildInputs ? [], + extraBuildInputs ? [ ], + extraNativeBuildInputs ? [ ], }: stdenvNoCC.mkDerivation { name = "${name}-src";