diff --git a/.gitignore b/.gitignore index 056dbb2..c07d5f6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ !.gitignore !github2forgejo +!*.lock !*.md +!*.nix diff --git a/README.md b/README.md index 1a17f27..f42e06b 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,41 @@ Plain simple, just install [Nushell](https://nushell.sh) and run the script: ./github2forgejo --help ``` +
+Help Output + +``` +Migrates a GitHub users repositories to a Forgejo instance. + +Accepted environment variables: + + GITHUB_USER: The user to fetch the repositories from. + GITHUB_TOKEN: An access token for fetching private repositories. Optional. + + FORGEJO_URL: The URL to the Forgejo instance. Must include the protocol (https://). + FORGEJO_USER: The user to migrate the repositories to. + FORGEJO_TOKEN: An access token for the specified user. + + STRATEGY: + The strategy. Valid options are "mirrored" or "cloned" (case insensitive). + "mirrored" will mirror the repository and tell the Forgejo instance to + periodically update it, "cloned" will only clone once. "cloned" is + useful if you are never going to use GitHub again. + + FORCE_SYNC: + Whether to delete a mirrored repo from the Forgejo instance if the + source on GitHub doesn't exist anymore. Must be either "true" or "false". + +To leave an environment variable unspecified, set it to an empty string. + +Usage: + > github2forgejo + +Flags: + -h, --help - Display the help message for this command +``` +
+ You can either specify all the environment variables for a uninteractive run, or run the script like so: @@ -17,6 +52,69 @@ And get a nice interactive experience. This works on any Forgejo instance. +You can also set up a systemd service and timer to run every once in a while. + +Use the flake, like so: + +```nix +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + github2forgejo = { + url = "github:RGBCube/GitHub2Forgejo"; + + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { nixpkgs, github2forgejo, ... }: let inherit (nixpkgs) lib; in { + nixosConfigurations.myserver = lib.nixosSystem { + modules = [ + github2forgejo.nixosModules.default + + { + nixpkgs.overlays = [ github2forgejo.overlays.default ]; + + services.github2forgejo = { + enable = true; + + # Something along the lines of: + # + # GITHUB_USER="RGBCube" + # GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + # FORGEJO_URL="https://git.rgbcu.be/" + # FORGEJO_USER="RGBCube" + # FORGEJO_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + # STRATEGY="mirrored" + # FORCE_SYNC="true" + # + # Do `GITHUB_TOKEN=""` if you want to only mirror public repositories of a person. + # You HAVE TO set each one of these. Leaving one unset will make the systemd unit fail! + environmentFile = "/secrets/github2forgejo.env"; + + # The default runs every day at midnight. But you can override it like so: + # + # timerConfig = { + # OnCalendar = "00:05"; + # RandomizedDelaySec = "5h"; + # Persistent = true; + # }; + # + # Or you can disable the timer by setting `timerConfig` to null: + # + # timerConfig = null; + } + } + ]; + } + }; +} +``` + +The script is also available as a package, you just need to use the +`packages..default` or `packages..github2forgejo` outputs. + ## FAQ ### What is the difference between mirroring and cloning? diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..1383f19 --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1716715802, + "narHash": "sha256-usk0vE7VlxPX8jOavrtpOqphdfqEQpf9lgedlY/r66c=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e2dd4e18cc1c7314e24154331bae07df76eb582f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "systems": "systems" + } + }, + "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..7f8752c --- /dev/null +++ b/flake.nix @@ -0,0 +1,115 @@ +{ + description = "GitHub to Forgejo migration script"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + systems.url = "github:nix-systems/default"; + }; + + outputs = { self, nixpkgs, systems }: let + inherit (nixpkgs) lib; + + eachSystem = lib.genAttrs (import systems); + in { + packages = eachSystem (system: let pkgs = import nixpkgs { inherit system; }; in rec { + inherit (self.overlays.github2forgejo pkgs pkgs) github2forgejo; + + default = github2forgejo; + }); + + overlays = rec { + default = github2forgejo; + github2forgejo = (final: super: { + github2forgejo = super.callPackage ./package.nix {}; + }); + }; + + nixosModules = rec { + default = github2forgejo; + github2forgejo = { config, utils, lib, pkgs, ... }: let + cfg = config.services.github2forgejo; + in { + options.services.github2forgejo = { + enable = lib.mkEnableOption (lib.mdDoc "the github2forgejo timer"); + package = lib.mkPackageOption pkgs "github2forgejo" {}; + + environmentFile = lib.mkOption { + type = lib.types.path; + default = null; + description = lib.mdDoc '' + File containing environment variables required by GitHub2Forgejo, + in the format of an EnvironmentFile as described by {manpage}`systemd.exec(5)`. + + You must set ALL of these environment variables: + + GITHUB_USER: The user to fetch the repositories from. + GITHUB_TOKEN: An access token for fetching private repositories. Optional. + + FORGEJO_URL: The URL to the Forgejo instance. Must include the protocol (https://). + FORGEJO_USER: The user to migrate the repositories to. + FORGEJO_TOKEN: An access token for the specified user. + + STRATEGY: + The strategy. Valid options are "mirrored" or "cloned" (case insensitive). + "mirrored" will mirror the repository and tell the Forgejo instance to + periodically update it, "cloned" will only clone once. "cloned" is + useful if you are never going to use GitHub again. + + FORCE_SYNC: + Whether to delete a mirrored repo from the Forgejo instance if the + source on GitHub doesn't exist anymore. Must be either "true" or "false". + + You must set an environment variable to an empty string to leave it "unset". + ''; + + example = "/secrets/github2forgejo.env"; + }; + + timerConfig = lib.mkOption { + type = with lib.types; nullOr (attrsOf utils.systemdUtils.unitOptions.unitOption); + default = { + OnCalendar = "daily"; + Persistent = true; + }; + + description = lib.mdDoc '' + When to run the script. See {manpage}`systemd.timer(5)` for + details. If null, no timer will be created and the script + will only run when explicitly started. + ''; + + example = { + OnCalendar = "00:05"; + RandomizedDelaySec = "5h"; + Persistent = true; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.github2forgejo = { + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + restartIfChanged = false; + + serviceConfig = { + Type = "oneshot"; + ExecStart = lib.getExe cfg.package; + + User = "github2forgejo"; + DynamicUser = true; + + EnvironmentFile = cfg.environmentFile; + }; + }; + + systemd.timers.github2forgejo = lib.mkIf (cfg.timerConfig != null) { + wantedBy = [ "timers.target" ]; + timerConfig = cfg.timerConfig; + }; + }; + }; + }; + }; +} diff --git a/package.nix b/package.nix new file mode 100644 index 0000000..128ec13 --- /dev/null +++ b/package.nix @@ -0,0 +1,43 @@ +{ + lib, + stdenvNoCC, + + nushell, +}: + +stdenvNoCC.mkDerivation { + name = "github2forgejo"; + version = "master"; + + src = ./.; + + dontBuild = true; + dontConfigure = true; + + nativeBuildInputs = [ nushell ]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp github2forgejo $out/bin + + runHook postInstall + ''; + + fixupPhase = '' + runHook preFixup + + substituteInPlace $out/bin/github2forgejo \ + --replace '/usr/bin/env nu' '${nushell}/bin/nu' + + runHook postFixup + ''; + + meta = with lib; { + description = "GitHub to Forgejo migration script"; + homepage = "https://git.rgbcu.be/RGBCube/GitHub2Forgejo"; + license = licenses.gpl3Only; + maintainers = with maintainers; [ RGBCube ]; + }; +}