on master help sign in
Merge pull request #613 from obsidiansystems/an@private-git-test

Create test framework for `ob thunk pack` on private repos

commit528ef0bf1577de8e6c5b1c3a9f5a6909c94b2a9c authorElliot Cameron <3noch@users.noreply.github.com> dateWed 8 Jan 2020, 19:18 (7 years ago) parent01dcec65718d06
4 files changed+211−167
all-builds.nix+97 all-tests.nix+107 jobsets.nix−71 release.nix+7−96
all-builds.nixnew file+97
@@ -0,0 +1,97 @@
1+{ self-args ? {
2+ config.android_sdk.accept_license = true;
3+ iosSdkVersion = "10.2";
4+ }
5+, local-self ? import ./. self-args
6+, supportedSystems ? [ "x86_64-linux" "x86_64-darwin" ]
7+}:
8+
9+let
10+ inherit (local-self.nixpkgs) lib runCommand nix;
11+ cacheBuildSystems = supportedSystems;
12+
13+ obeliskPackagesCommon = [
14+ "obelisk-frontend"
15+ "obelisk-route"
16+ "obelisk-executable-config-lookup"
17+ ];
18+
19+ obeliskPackagesBackend = obeliskPackagesCommon ++ [
20+ "obelisk-asset-manifest"
21+ "obelisk-asset-serve-snap"
22+ "obelisk-backend"
23+ "obelisk-cliapp"
24+ "obelisk-command"
25+ "obelisk-executable-config-inject"
26+ "obelisk-frontend"
27+ "obelisk-run"
28+ "obelisk-route"
29+ "obelisk-selftest"
30+ "obelisk-snap-extras"
31+ ];
32+
33+ pnameToAttrs = pkgsSet: pnames:
34+ lib.listToAttrs (map
35+ (name: { inherit name; value = pkgsSet.${name}; })
36+ pnames);
37+
38+ concatDepends = let
39+ extractDeps = x: (x.override {
40+ mkDerivation = drv: {
41+ out = builtins.concatLists [
42+ (drv.buildDepends or [])
43+ (drv.libraryHaskellDepends or [])
44+ (drv.executableHaskellDepends or [])
45+ ];
46+ };
47+ }).out;
48+ in pkgAttrs: builtins.concatLists (map extractDeps (builtins.attrValues pkgAttrs));
49+
50+ perPlatform = lib.genAttrs cacheBuildSystems (system: let
51+ obelisk = import ./. (self-args // { inherit system; });
52+ reflex-platform = obelisk.reflex-platform;
53+ ghc = pnameToAttrs
54+ obelisk.haskellPackageSets.ghc
55+ obeliskPackagesBackend;
56+ ghcjs = pnameToAttrs
57+ obelisk.haskellPackageSets.ghcjs
58+ obeliskPackagesCommon;
59+ cachePackages = builtins.concatLists [
60+ (builtins.attrValues ghc)
61+ (builtins.attrValues ghcjs)
62+ (concatDepends ghc)
63+ (concatDepends ghcjs)
64+ (lib.optional reflex-platform.androidSupport androidSkeleton)
65+ (lib.optional reflex-platform.iosSupport iosSkeleton)
66+ [ command serverSkeletonExe serverSkeletonShell ]
67+ ];
68+ command = obelisk.command;
69+ skeleton = import ./skeleton { inherit obelisk; };
70+ serverSkeletonExe = skeleton.exe;
71+ # TODO fix nixpkgs so it doesn't try to run the result of haskell shells as setup hooks.
72+ serverSkeletonShell = local-self.nixpkgs.runCommand "shell-safe-for-dep" {} ''
73+ touch "$out"
74+ echo "return" >> "$out"
75+ cat "${skeleton.shells.ghc}" >> "$out"
76+ '';
77+ androidSkeleton = (import ./skeleton { inherit obelisk; }).android.frontend;
78+ iosSkeleton = (import ./skeleton { inherit obelisk; }).ios.frontend;
79+ in {
80+ inherit
81+ command
82+ ghc ghcjs
83+ serverSkeletonExe
84+ serverSkeletonShell
85+ ;
86+ cache = reflex-platform.pinBuildInputs "obelisk-${system}" cachePackages;
87+ } // lib.optionalAttrs reflex-platform.androidSupport {
88+ inherit androidSkeleton;
89+ } // lib.optionalAttrs reflex-platform.iosSupport {
90+ inherit iosSkeleton;
91+ });
92+
93+ metaCache = local-self.reflex-platform.pinBuildInputs
94+ "obelisk-everywhere"
95+ (map (a: a.cache) (builtins.attrValues perPlatform));
96+
97+in perPlatform // { inherit metaCache; }
all-tests.nixnew file+107
@@ -0,0 +1,107 @@
1+{
2+ supportedSystems ? [ builtins.currentSystem ]
3+}:
4+let
5+ nginxRoot = "/run/nginx";
6+ obelisk = import ./default.nix {};
7+ # Get NixOS a pre-release 20.03 that contains the python based tests and recursive nix
8+ pkgs = import (builtins.fetchTarball https://github.com/nixos/nixpkgs/archive/3de5266.tar.gz) {};
9+ sshKeys = import (pkgs.path + /nixos/tests/ssh-keys.nix) pkgs;
10+ make-test = import (pkgs.path + /nixos/tests/make-test-python.nix);
11+ obelisk-everywhere = (import ./all-builds.nix { inherit supportedSystems; }).x86_64-linux.cache;
12+ snakeOilPrivateKey = sshKeys.snakeOilPrivateKey.text;
13+ snakeOilPublicKey = sshKeys.snakeOilPublicKey;
14+in
15+ make-test ({...}: {
16+ name = "obelisk";
17+ nodes = {
18+ githost = {
19+ networking.firewall.allowedTCPPorts = [ 22 80 ];
20+ services.openssh = {
21+ enable = true;
22+ };
23+ environment.systemPackages = [
24+ pkgs.git
25+ ];
26+ users.users.root.openssh.authorizedKeys.keys = [
27+ snakeOilPublicKey
28+ ];
29+ };
30+
31+ client = {
32+ imports = [
33+ (pkgs.path + /nixos/modules/installer/cd-dvd/channel.nix)
34+ ];
35+ nix.useSandbox = false;
36+ nix.binaryCaches = [];
37+ environment.systemPackages = [
38+ obelisk.command
39+ obelisk.shell
40+ obelisk-everywhere
41+ pkgs.git
42+ ];
43+ };
44+ };
45+
46+ testScript =
47+ let
48+ privateKeyFile = pkgs.writeText "id_rsa" ''${snakeOilPrivateKey}'';
49+ sshConfigFile = pkgs.writeText "ssh_config" ''
50+ Host *
51+ StrictHostKeyChecking no
52+ UserKnownHostsFile=/dev/null
53+ ConnectionAttempts=1
54+ ConnectTimeout=1
55+ IdentityFile=~/.ssh/id_rsa
56+ User=root
57+ '';
58+ in ''
59+ start_all()
60+ githost.wait_for_open_port("22")
61+
62+ with subtest("test obelisk is installed"):
63+ client.succeed("ob --help")
64+
65+ with subtest("test the client can access the server via ssh"):
66+ client.succeed("mkdir -p ~/.ssh/")
67+ client.succeed(
68+ "cp ${privateKeyFile} ~/.ssh/id_rsa"
69+ )
70+ client.succeed("chmod 600 ~/.ssh/id_rsa")
71+ client.wait_until_succeeds(
72+ "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa githost true"
73+ )
74+ client.succeed(
75+ "cp ${sshConfigFile} ~/.ssh/config"
76+ )
77+ client.wait_until_succeeds("ssh githost true")
78+
79+ with subtest("test a remote bare repo can be started"):
80+ githost.succeed("mkdir -p ~/myorg/myapp.git")
81+ githost.succeed("cd ~/myorg/myapp.git && git init --bare")
82+
83+ with subtest("test a git project can be configured with a remote using ssh"):
84+ client.succeed("mkdir -p ~/code/myapp")
85+ client.succeed("cd ~/code/myapp && git init")
86+ client.succeed("cd ~/code/myapp && touch README")
87+ client.succeed("cd ~/code/myapp && git add .")
88+ client.succeed('git config --global user.email "you@example.com"')
89+ client.succeed('git config --global user.name "Your Name"')
90+ client.succeed('cd ~/code/myapp && git commit -m "Initial"')
91+ client.succeed(
92+ "cd ~/code/myapp && git remote add origin root@githost:/root/myorg/myapp.git"
93+ )
94+
95+ with subtest("test pushing code to the remote"):
96+ client.succeed("cd ~/code/myapp && git push -u origin master")
97+ client.succeed("cd ~/code/myapp && git status")
98+
99+ with subtest("test obelisk can pack"):
100+ client.succeed("ob thunk pack ~/code/myapp")
101+ client.succeed("grep -qF 'git' ~/code/myapp/default.nix")
102+ client.succeed("grep -qF 'myorg' ~/code/myapp/git.json")
103+
104+ with subtest("test obelisk can detect private repos"):
105+ client.succeed("""grep -qF '"private": false' ~/code/myapp/git.json""")
106+ '';
107+ }) {}
jobsets.nixdeleted−71
@@ -1,71 +0,0 @@
1−{ prs }:
2−
3−let
4− self = import ./. {};
5− pkgs = self.nixpkgs;
6− mkFetchGithub = value: {
7− inherit value;
8− type = "git";
9− emailresponsible = false;
10− };
11−in
12−with pkgs.lib;
13−let
14− defaults = jobs: {
15− inherit (jobs) description;
16− enabled = 1;
17− hidden = false;
18− keepnr = 10;
19− schedulingshares = 100;
20− checkinterval = 120;
21− enableemail = false;
22− emailoverride = "";
23− nixexprinput = "obelisk";
24− nixexprpath = "release.nix";
25− inputs = jobs.inputs // {
26− nixpkgs = {
27− type = "git";
28− value = "https://github.com/NixOS/nixpkgs-channels nixos-unstable";
29− emailresponsible = false;
30− };
31− };
32− self-args = {
33− type = "nix";
34− value = "{ config.android_sdk.accept_license = true; }";
35− emailresponsible = false;
36− };
37− };
38− branchJobset = branch: defaults {
39− description = "obelisk-${branch}";
40− inputs = {
41− obelisk = {
42− value = "https://github.com/obsidiansystems/obelisk ${branch}";
43− type = "git";
44− emailresponsible = false;
45− };
46− };
47− };
48− makePr = num: info: {
49− name = "obelisk-pr-${num}";
50− value = defaults {
51− description = "#${num}: ${info.title}";
52− inputs = {
53− obelisk = {
54− #NOTE: This should really use "pull/${num}/merge"; however, GitHub's
55− #status checks only operate on PR heads. This creates a race
56− #condition, which can currently only be solved by requiring PRs to be
57− #up to date before they're merged. See
58− #https://github.com/isaacs/github/issues/1002
59− value = "https://github.com/obsidiansystems/obelisk pull/${num}/head";
60− type = "git";
61− emailresponsible = false;
62− };
63− };
64− };
65− };
66− processedPrs = mapAttrs' makePr (builtins.fromJSON (builtins.readFile prs));
67− jobsetsAttrs = processedPrs //
68− genAttrs ["master"] branchJobset;
69−in {
70− jobsets = pkgs.writeText "spec.json" (builtins.toJSON jobsetsAttrs);
71−}
release.nix+7−96
@@ -1,97 +1,8 @@
1−{ self-args ? {
2− config.android_sdk.accept_license = true;
3− iosSdkVersion = "10.2";
4− }
5−, local-self ? import ./. self-args
1+{
2+ supportedSystems ? [ "x86_64-linux" "x86_64-darwin" ]
63}:
7−
8−let
9− inherit (local-self.nixpkgs) lib runCommand nix;
10−
11− cacheBuildSystems = [ "x86_64-linux" "x86_64-darwin" ];
12−
13− obeliskPackagesCommon = [
14− "obelisk-frontend"
15− "obelisk-route"
16− "obelisk-executable-config-lookup"
17− ];
18−
19− obeliskPackagesBackend = obeliskPackagesCommon ++ [
20− "obelisk-asset-manifest"
21− "obelisk-asset-serve-snap"
22− "obelisk-backend"
23− "obelisk-cliapp"
24− "obelisk-command"
25− "obelisk-executable-config-inject"
26− "obelisk-frontend"
27− "obelisk-run"
28− "obelisk-route"
29− "obelisk-selftest"
30− "obelisk-snap-extras"
31− ];
32−
33− pnameToAttrs = pkgsSet: pnames:
34− lib.listToAttrs (map
35− (name: { inherit name; value = pkgsSet.${name}; })
36− pnames);
37−
38− concatDepends = let
39− extractDeps = x: (x.override {
40− mkDerivation = drv: {
41− out = builtins.concatLists [
42− (drv.buildDepends or [])
43− (drv.libraryHaskellDepends or [])
44− (drv.executableHaskellDepends or [])
45− ];
46− };
47− }).out;
48− in pkgAttrs: builtins.concatLists (map extractDeps (builtins.attrValues pkgAttrs));
49−
50− perPlatform = lib.genAttrs cacheBuildSystems (system: let
51− obelisk = import ./. (self-args // { inherit system; });
52− reflex-platform = obelisk.reflex-platform;
53− ghc = pnameToAttrs
54− obelisk.haskellPackageSets.ghc
55− obeliskPackagesBackend;
56− ghcjs = pnameToAttrs
57− obelisk.haskellPackageSets.ghcjs
58− obeliskPackagesCommon;
59− cachePackages = builtins.concatLists [
60− (builtins.attrValues ghc)
61− (builtins.attrValues ghcjs)
62− (concatDepends ghc)
63− (concatDepends ghcjs)
64− (lib.optional reflex-platform.androidSupport androidSkeleton)
65− (lib.optional reflex-platform.iosSupport iosSkeleton)
66− [ command serverSkeletonExe serverSkeletonShell ]
67− ];
68− command = obelisk.command;
69− skeleton = import ./skeleton { inherit obelisk; };
70− serverSkeletonExe = skeleton.exe;
71− # TODO fix nixpkgs so it doesn't try to run the result of haskell shells as setup hooks.
72− serverSkeletonShell = local-self.nixpkgs.runCommand "shell-safe-for-dep" {} ''
73− touch "$out"
74− echo "return" >> "$out"
75− cat "${skeleton.shells.ghc}" >> "$out"
76− '';
77− androidSkeleton = (import ./skeleton { inherit obelisk; }).android.frontend;
78− iosSkeleton = (import ./skeleton { inherit obelisk; }).ios.frontend;
79− in {
80− inherit
81− command
82− ghc ghcjs
83− serverSkeletonExe
84− serverSkeletonShell
85− ;
86− cache = reflex-platform.pinBuildInputs "obelisk-${system}" cachePackages;
87− } // lib.optionalAttrs reflex-platform.androidSupport {
88− inherit androidSkeleton;
89− } // lib.optionalAttrs reflex-platform.iosSupport {
90− inherit iosSkeleton;
91− });
92−
93− metaCache = local-self.reflex-platform.pinBuildInputs
94− "obelisk-everywhere"
95− (map (a: a.cache) (builtins.attrValues perPlatform));
96−
97−in perPlatform // { inherit metaCache; }
4+{
5+ recurseForDerivations = true;
6+ build = import ./all-builds.nix { inherit supportedSystems; };
7+ test = import ./all-tests.nix { inherit supportedSystems; };
8+}