anchor.diff:              "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${auth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers"
           )
         '' + optionalString doSetup ''
  -        gitlab.succeed(
  -            """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createProject} http://gitlab/api/v4/projects)" = "201" ]"""
  -        )
  -        gitlab.succeed(
  -            """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${putFile} http://gitlab/api/v4/projects/2/repository/files/some-file.txt)" = "201" ]"""
  -        )
  +        with subtest("Create user Alice"):
  +            gitlab.succeed(
  +                """[ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createUserAlice} http://gitlab/api/v4/users)" = "201" ]"""
  +            )
  +            gitlab.succeed(
  +                "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${aliceAuth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers-alice"
  +            )
  +
  +        with subtest("Create user Bob"):
  +            gitlab.succeed(
  +                """ [ "$(curl -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H @/tmp/headers -d @${createUserBob} http://gitlab/api/v4/users)" = "201" ]"""
  +            )
  +            gitlab.succeed(
  +                "echo \"Authorization: Bearer $(curl -X POST -H 'Content-Type: application/json' -d @${bobAuth} http://gitlab/oauth/token | ${pkgs.jq}/bin/jq -r '.access_token')\" >/tmp/headers-bob"
  +            )
  +
  +        with subtest("Setup Git and SSH for Alice"):
  +            gitlab.succeed("git config --global user.name Alice")
  +            gitlab.succeed("git config --global user.email alice@nixos.invalid")
  +            gitlab.succeed("mkdir -m 700 /root/.ssh")
  +            gitlab.succeed("cat ${snakeOilPrivateKey} > /root/.ssh/id_ecdsa")
  +            gitlab.succeed("chmod 600 /root/.ssh/id_ecdsa")
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-alice -d @${aliceAddSSHKey} \
  +                    http://gitlab/api/v4/user/keys)" = "201" ]
  +                """
  +            )
  +
  +        with subtest("Create a new repository"):
  +            # Alice creates a new repository
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-alice \
  +                    -d @${createProjectAlice} \
  +                    http://gitlab/api/v4/projects)" = "201" ]
  +                """
  +            )
  +
  +            # Alice commits an initial commit
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-alice \
  +                    -d @${putFile} \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/repository/files/some-file.txt)" = "201" ]"""
  +            )
  +
  +        with subtest("git clone over HTTP"):
  +            gitlab.succeed(
  +                """git clone http://gitlab/alice/${aliceProjectName}.git clone-via-http""",
  +                timeout=15
  +            )
  +
  +        with subtest("Push a commit via SSH"):
  +            gitlab.succeed(
  +                f"""GIT_SSH_COMMAND="{GIT_SSH_COMMAND}" git clone gitlab@gitlab:alice/${aliceProjectName}.git""",
  +                timeout=15
  +            )
  +            gitlab.succeed(
  +                """echo "a commit sent over ssh" > ${aliceProjectName}/ssh.txt"""
  +            )
  +            gitlab.succeed(
  +                """
  +                cd ${aliceProjectName} || exit 1
  +                git add .
  +                """
  +            )
  +            gitlab.succeed(
  +                """
  +                cd ${aliceProjectName} || exit 1
  +                git commit -m "Add a commit to be sent over ssh"
  +                """
  +            )
  +            gitlab.succeed(
  +                f"""
  +                cd ${aliceProjectName} || exit 1
  +                GIT_SSH_COMMAND="{GIT_SSH_COMMAND}" git push --set-upstream origin master
  +                """,
  +                timeout=15
  +            )
  +
  +        with subtest("Fork a project"):
  +            # Bob forks Alice's project
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-bob \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/fork)" = "201" ]
  +                """
  +            )
  +
  +            # Bob creates a commit
  +            gitlab.wait_until_succeeds(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-bob \
  +                    -d @${putFile} \
  +                    http://gitlab/api/v4/projects/${bobProjectId}/repository/files/some-other-file.txt)" = "201" ]
  +                """
  +            )
  +
  +        with subtest("Create a Merge Request"):
  +            # Bob opens a merge request against Alice's repository
  +            gitlab.wait_until_succeeds(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-bob \
  +                    -d @${mergeRequest} \
  +                    http://gitlab/api/v4/projects/${bobProjectId}/merge_requests)" = "201" ]
  +                """
  +            )
  +
  +            # Alice merges the MR
  +            gitlab.wait_until_succeeds(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X PUT \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-alice \
  +                    -d @${mergeRequest} \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/merge_requests/1/merge)" = "200" ]
  +                """
  +            )
  +
  +        with subtest("Create an Issue"):
  +            # Bob opens an issue on Alice's repository
  +            gitlab.succeed(
  +                """[ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X POST \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-bob \
  +                    -d @${newIssue} \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/issues)" = "201" ]
  +                """
  +            )
  +
  +            # Alice closes the issue
  +            gitlab.wait_until_succeeds(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -X PUT \
  +                    -H 'Content-Type: application/json' \
  +                    -H @/tmp/headers-alice -d @${closeIssue} http://gitlab/api/v4/projects/${aliceProjectId}/issues/1)" = "200" ]
  +                """
  +            )
         '' + ''
  -        gitlab.succeed(
  -            """[ "$(curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.gz)" = "200" ]"""
  -        )
  -        gitlab.succeed(
  -            """curl -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.gz > /tmp/archive.tar.gz"""
  -        )
  -        gitlab.succeed(
  -            """[ "$(curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.bz2)" = "200" ]"""
  -        )
  -        gitlab.succeed(
  -            """curl -o /dev/null -w '%{http_code}' -H @/tmp/headers http://gitlab/api/v4/projects/2/repository/archive.tar.bz2 > /tmp/archive.tar.bz2"""
  -        )
  -        gitlab.succeed("test -s /tmp/archive.tar.gz")
  -        gitlab.succeed("test -s /tmp/archive.tar.bz2")
  +        with subtest("Download archive.tar.gz"):
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -H @/tmp/headers-alice \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.gz)" = "200" ]
  +                """
  +            )
  +            gitlab.succeed(
  +                """
  +                curl \
  +                    -H @/tmp/headers-alice \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.gz > /tmp/archive.tar.gz
  +                """
  +            )
  +            gitlab.succeed("test -s /tmp/archive.tar.gz")
  +
  +        with subtest("Download archive.tar.bz2"):
  +            gitlab.succeed(
  +                """
  +                [ "$(curl \
  +                    -o /dev/null \
  +                    -w '%{http_code}' \
  +                    -H @/tmp/headers-alice \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.bz2)" = "200" ]
  +                """
  +            )
  +            gitlab.succeed(
  +                """
  +                curl \
  +                    -H @/tmp/headers-alice \
  +                    http://gitlab/api/v4/projects/${aliceProjectId}/repository/archive.tar.bz2 > /tmp/archive.tar.bz2
  +                """
  +            )
  +            gitlab.succeed("test -s /tmp/archive.tar.bz2")
         '';
   
     in ''
  
positive.code:         password = initialRootPassword;
        });
  
        createProject = pkgs.writeText "create-project.json" (builtins.toJSON {
          name = "test";
        });
  
        putFile = pkgs.writeText "put-file.json" (builtins.toJSON {
  
negative.code:           };
          };
        };
  
        services.openssh.enable = true;
  
        services.dovecot2 = {
          enable = true;
  