diff --git a/Handler/Shared.hs b/Handler/Shared.hs index fc68588..cc14542 100644 --- a/Handler/Shared.hs +++ b/Handler/Shared.hs @@ -78,14 +78,17 @@ getPublicSubmissionBranch = T.pack . (printf "submission-%05d") . fromSqlKey getPublicSubmissionUrl :: RepoScheme -> Text -> Maybe Repo -> Text -> Text getPublicSubmissionUrl SelfHosted repoHost _ bareRepoName = repoHost ++ bareRepoName getPublicSubmissionUrl Branches _ (Just repo) _ = repoUrl repo +getPublicSubmissionUrl NoInternalGitServer _ (Just repo) _ = repoUrl repo getReadOnlySubmissionUrl :: RepoScheme -> Repo -> Text -> Text getReadOnlySubmissionUrl SelfHosted _ bareRepoName = gitReadOnlyServer ++ bareRepoName getReadOnlySubmissionUrl Branches repo _ = repoUrl repo +getReadOnlySubmissionUrl NoInternalGitServer repo _ = repoUrl repo browsableGitRepoBranch :: RepoScheme -> Repo -> Text -> Text -> Text browsableGitRepoBranch SelfHosted _ bareRepoName branch = (browsableGitRepo bareRepoName) ++ "/" ++ branch ++ "/" browsableGitRepoBranch Branches repo _ branch = sshToHttps (repoUrl repo) branch +browsableGitRepoBranch NoInternalGitServer repo _ branch = sshToHttps (repoUrl repo) branch sshToHttps :: Text -> Text -> Text sshToHttps url branch = "https://" ++ (T.replace ".git" "" $ T.replace ":" "/" $ T.replace "ssh://" "" $ T.replace "git@" "" url) ++ "/tree/" ++ branch diff --git a/Handler/ShowChallenge.hs b/Handler/ShowChallenge.hs index ab4c3c9..461c54e 100644 --- a/Handler/ShowChallenge.hs +++ b/Handler/ShowChallenge.hs @@ -526,20 +526,25 @@ idToBeShown _ maybeUser = Nothing -> defaultIdToBe where defaultIdToBe = "YOURID" :: Text +externalRepoPlaceholder :: Text +externalRepoPlaceholder = "URL_TO_YOUR_REPO" + defaultRepo :: RepoScheme -> Text -> Challenge -> Repo -> Maybe (Entity User) -> Text defaultRepo SelfHosted repoHost challenge _ maybeUser = repoHost ++ (idToBeShown challenge maybeUser) ++ "/" ++ (challengeName challenge) defaultRepo Branches _ _ repo _ = repoUrl repo +defaultRepo NoInternalGitServer _ _ _ _ = externalRepoPlaceholder defaultBranch :: IsString a => RepoScheme -> Maybe a defaultBranch SelfHosted = Just "master" defaultBranch Branches = Nothing +defaultBranch NoInternalGitServer = Nothing challengeHowTo :: Challenge -> AppSettings -> Repo -> Text -> Bool -> Bool -> Maybe Text -> Maybe Text -> WidgetFor App () challengeHowTo challenge settings repo shownId isIDSet isSSHUploaded mAltRepoScheme mToken = $(widgetFile "challenge-how-to") where myBranch = "my-brilliant-branch" :: Text urlToYourRepo = case mAltRepoScheme of Just altRepoScheme -> encodeSlash (altRepoScheme <> (challengeName challenge)) - Nothing -> "URL_TO_YOUR_REPO" + Nothing -> externalRepoPlaceholder postHealR :: ChallengeId -> Handler TypedContent postHealR challengeId = runViewProgress $ doHeal challengeId @@ -1086,6 +1091,8 @@ checkRepoAvailibility challengeId repoId chan = do challengeSubmissionWidget :: (ToMarkup a1, ToWidget App a2) => a2 -> a1 -> Challenge -> WidgetFor App () challengeSubmissionWidget formWidget formEnctype challenge = $(widgetFile "challenge-submission") +externalRepoInfo settings = $(widgetFile "external-repo") + data ChallengeSubmissionData = ChallengeSubmissionData { challengeSubmissionDataDescription :: Maybe Text, challengeSubmissionDataTags :: Maybe Text, diff --git a/Settings.hs b/Settings.hs index c9908c8..8ca7a92 100644 --- a/Settings.hs +++ b/Settings.hs @@ -21,11 +21,12 @@ import Web.Announcements (AnnouncementHook, toAnnouncementHook) import qualified Jose.Jwk as JWK -data RepoScheme = SelfHosted | Branches +data RepoScheme = SelfHosted | Branches | NoInternalGitServer deriving (Eq, Show) toRepoScheme :: Text -> RepoScheme toRepoScheme "branches" = Branches +toRepoScheme "no-internal-git-server" = NoInternalGitServer toRepoScheme _ = SelfHosted data TagPermissions = OnlyAdminCanAddNewTags | EverybodyCanAddNewTags diff --git a/config/settings.yml b/config/settings.yml index 20992c7..fef0e65 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -9,6 +9,14 @@ ip-from-header: "_env:IP_FROM_HEADER:false" var-dir: "_env:VAR_DIR:." contact-email: "_env:CONTACT_EMAIL:filipg@amu.edu.pl" repo-host: "_env:REPO_HOST:ssh://gitolite@gonito.net/" +# How the git repos are handled +# - selfhosted - there is a git server (e.g. Gitolite) on the same +# host as the Gonito instance +# - branches - solutions are submitted to the same repo as the task +# (this is good for an internal repo within a company) +# - no-internal-git-server - there is no git server assumed, though +# REPO_HOST can be still specified +# for publishing opened solutions repo-scheme: "_env:REPO_SCHEME:selfhosted" tag-permissions: "_env:TAG_PERMISSIONS:only-admin-can-add-new-tags" auto-opening: "_env:AUTO_OPENING:false" diff --git a/docker-compose-simple.yml b/docker-compose-simple.yml index 25f1125..1138570 100644 --- a/docker-compose-simple.yml +++ b/docker-compose-simple.yml @@ -12,6 +12,8 @@ services: - ADMINPASS=$GONITO_ADMINPASS - LOCATION=$GONITO_LOCATION - APPROOT=$GONITO_APPROOT + - REPO_HOST=$GONITO_REPO_HOST + - REPO_SCHEME=$GONITO_REPO_SCHEME - LEADERBOARD_STYLE=${GONITO_LEADERBOARD_STYLE:-by-tag} - AUTO_OPENING=${GONITO_AUTO_OPENING:-false} - IS_PUBLIC=${GONITO_IS_PUBLIC:-true} diff --git a/docker-compose.yml b/docker-compose.yml index bd000b9..719e270 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,8 @@ services: - ADMINPASS=$GONITO_ADMINPASS - LOCATION=$GONITO_LOCATION - APPROOT=$GONITO_APPROOT + - REPO_HOST=$GONITO_REPO_HOST + - REPO_SCHEME=$GONITO_REPO_SCHEME - LEADERBOARD_STYLE=${GONITO_LEADERBOARD_STYLE:-by-tag} - AUTO_OPENING=${GONITO_AUTO_OPENING:-false} - IS_PUBLIC=${GONITO_IS_PUBLIC:-true} diff --git a/sample.env b/sample.env index a342150..1200839 100644 --- a/sample.env +++ b/sample.env @@ -5,6 +5,11 @@ GONITO_ADMINPASS=Ahxuz5du GONITO_LOCATION=test GONITO_ARENA_VOLUME=/home/user/arena GONITO_APPROOT=https://localhost:443 +# URL scheme for a git server associated with the instance +GONITO_REPO_HOST=ssh://gitolite@gonito.net/ +# How git repos are handled, 'selfhosted', 'branches' or +# 'no-internal-git-server' +GONITO_REPO_SCHEME=branches GONITO_LEADERBOARD_STYLE=by-tag GONITO_AUTO_OPENING=false NGINX_CERTIFICATE_DIR=/home/user/certs diff --git a/templates/challenge-how-to.hamlet b/templates/challenge-how-to.hamlet index 75c43dc..4b87f32 100644 --- a/templates/challenge-how-to.hamlet +++ b/templates/challenge-how-to.hamlet @@ -43,7 +43,7 @@ $case (appRepoScheme settings) \ and $if not isSSHUploaded \ upload your SSH public key - \ (see your account) if you want to have a repo hosted on Gonito.net, then: + \ (see your account) if you want to have a repo hosted on this instance, then: $maybe altRepoScheme <- mAltRepoScheme

(Depending on your setup, you might need to create the repo at your git server first; remember to initiate it without any commits!) @@ -53,23 +53,42 @@ $case (appRepoScheme settings)

       git clone --single-branch #{appRepoHost settings}#{shownId}/#{challengeName challenge}
 
-    

(Warning about empty repository is expected, don't worry about it.) +

(Warning about empty repository is expected, don't worry about it.) + + $maybe altRepoScheme <- mAltRepoScheme + ^{externalRepoInfo settings}

     cd #{challengeName challenge}
     git pull #{repoUrl repo}
 
-  

Using an external repository + $if isNothing mAltRepoScheme +

Using an external repository - $maybe serverPubKey <- (appServerSSHPublicKey settings) - $if isNothing mAltRepoScheme -

Alternatively, you can use any other Git repo, e.g. GitLab, GitHub or your own repo, make sure Gonito.net has access to your repo, either by making it public or giving read access to the SSH public key: - $else -

-        #{serverPubKey}
-  $nothing
-    $if isNothing mAltRepoScheme
-      

Alternatively, you can use any other Git repo, e.g. GitLab, GitHub or your own repo, make sure Gonito.net has access to your repo. +

Alternatively, you can use any other Git repo, e.g. GitLab, GitHub or your own repo. + + ^{externalRepoInfo settings} + + $of NoInternalGitServer + $maybe altRepoScheme <- mAltRepoScheme +

Make sure the repo #{altRepoScheme}#{challengeName challenge} exists. Note that it should be created as empty (do not create any default `README.md` file). + $nothing +

You need to have a repo at some external Git server (e.g. GitHub, GitLab or your own git server) for storing your solution. + +

Create a repo at your server. It should be created as empty (do **not** create any default `README.md` file). +

The repo should contain #{challengeName challenge} as part of its URL (preferably it should be the last part of the URL) + + ^{externalRepoInfo settings} + +

+      $maybe altRepoScheme <- mAltRepoScheme
+         git clone #{altRepoScheme}#{challengeName challenge}
+      $nothing
+         git clone URL_TO_YOUR_REPO
+
+    
+      cd #{challengeName challenge}
+      git pull #{repoUrl repo}
 
  $of Branches
     

Clone the repo: @@ -121,13 +140,15 @@ $case (appRepoScheme settings) $of SelfHosted

       git push origin #{myBranch}
-    

Repos hosted on Gonito.net +

Submit your solution to Gonito +

Repos hosted on this instance

If you use a repo hosted here, a submission and evaluation is triggered automatically. You'll see the evaluation results in your console while pushing. - $of Branches + $of _

       git push origin #{myBranch}
+    

Submit your solution to Gonito -

External repos +

Integration with external repos

If you use an external repo (e.g. at your own of Gitolite or at GitLab/GitHub), you can configure a webhook. $maybe token <- mToken diff --git a/templates/external-repo.hamlet b/templates/external-repo.hamlet new file mode 100644 index 0000000..0267258 --- /dev/null +++ b/templates/external-repo.hamlet @@ -0,0 +1,6 @@ + $maybe serverPubKey <- (appServerSSHPublicKey settings) +

Make sure Gonito.net has access to your repo, either by making it public or giving read access to the SSH public key: +

+         #{serverPubKey}
+    $nothing
+      

Make sure Gonito.net has access to your repo (e.g. by making it public).