1
0
Fork 0

Enable fdroid deployment

This commit is contained in:
Malte Brandy 2021-01-11 06:44:33 +01:00
parent cb149a93e1
commit a3873e4dcd
9 changed files with 148 additions and 93 deletions

View file

@ -117,7 +117,6 @@ in {
./roles/on-my-machine.nix
./roles/headless.nix
./roles/weechat
./roles/kassandra-server.nix
./roles/headless-mpd.nix
./roles/mail.nix
./roles/mail2rss.nix

View file

@ -1,12 +0,0 @@
{ pkgs, ... }: {
systemd.user.services.kassandra = {
Unit = { Description = "Kassandra Server"; };
Service = {
WorkingDirectory = "/var/www/kassandra";
ExecStart = "/var/www/kassandra/backend -b '::1' ";
Restart = "always";
Environment = "PATH=${pkgs.coreutils}/bin/:${pkgs.taskwarrior}/bin";
};
Install = { WantedBy = [ "default.target" ]; };
};
}

View file

@ -19,6 +19,7 @@ in {
../../roles/coturn.nix
../../roles/go-neb.nix
../../roles/laminar
../../roles/kassandra-server.nix
./web.nix
./mail.nix
./boot.nix
@ -38,7 +39,9 @@ in {
'';
startAgent = true;
};
java.enable = true;
};
nixpkgs.config.android_sdk.accept_license = true;
systemd.services."pg_backup" = {
script = let name = "matrix-synapse";
in ''

View file

@ -0,0 +1,14 @@
{ pkgs, ... }: {
systemd.services.kassandra = {
enable = true;
description = "Kassandra Server";
serviceConfig = let serverPath = "/var/cache/gc-links/kassandra-server";
in {
WorkingDirectory = serverPath;
ExecStart = "${serverPath}/backend -b '::1' ";
Restart = "always";
Environment = "PATH=${pkgs.coreutils}/bin/:${pkgs.taskwarrior}/bin";
User = "maralorn";
};
};
}

View file

@ -2,14 +2,26 @@
let
path = [ pkgs.git pkgs.nix pkgs.gnutar pkgs.gzip pkgs.openssh pkgs.laminar ];
setup = ''
set -e
export PATH=${lib.makeBinPath path}:$PATH
'';
repo = "/var/www/fdroid";
appName = "de.maralorn.kassandra";
deploy = "${pkgs.writeShellScript "deploy" ''
systemctl restart kassandra
VERSIONCODE="1"
rm ${repo}/repo/${appName}_$VERSIONCODE.apk
cp /var/cache/gc-links/kassandra-android/android-app-release-unsigned.apk ${repo}/unsigned/${appName}_$VERSIONCODE.apk
cd ${repo}
export PATH=/run/current-system/sw/bin:$PATH
export ANDROID_HOME=${pkgs.androidsdk_9_0}/libexec/android-sdk
fdroid publish
fdroid update
''}";
target = name: ''
set -e
${setup}
export HOME=$PWD
git clone git@localhost:kassandra2 kassandra
cd kassandra
git clone git@localhost:kassandra2 .
git show -q
echo "Evaluating nix-expression."
export FLAGS='--builders @/etc/nix/machines --max-jobs 1'
@ -19,11 +31,19 @@ let
laminarc set "RESULTDRV=$drv"
'';
in {
security.sudo.extraRules = [{
commands = [{
command = deploy;
options = [ "NOPASSWD" ];
}];
users = [ "laminar" ];
}];
services.laminar.cfgFiles.jobs = {
"kassandra.run" = pkgs.writeShellScript "kassandra" ''
${setup}
echo Launching and waiting for jobs lib, app, android and server
laminarc run kassandra-lib kassandra-android kassandra-app kassandra-server
/run/wrappers/bin/sudo ${deploy}
'';
"kassandra-lib.run" = pkgs.writeShellScript "kassandra-lib" (target "lib");
"kassandra-app.run" = pkgs.writeShellScript "kassandra-app" (target "app");

View file

@ -15,7 +15,9 @@ import Control.Concurrent.Async ( forConcurrently_
, race_
, withAsync
)
import Control.Concurrent.STM ( check )
import Control.Concurrent.STM ( check
, retry
)
import Control.Exception ( bracket
, catch
, handle
@ -23,6 +25,7 @@ import Control.Exception ( bracket
, throwIO
)
import Data.Bits ( Bits((.|.)) )
import qualified Data.Map as Map
import qualified Data.Sequence as Seq
import Data.String.Interpolate ( i )
import Data.Text ( isInfixOf
@ -33,7 +36,6 @@ import qualified Data.Text as T
import Data.Time ( diffUTCTime
, getCurrentTime
)
import qualified Data.Map as Map
import Relude
import Say ( say
, sayErr
@ -62,6 +64,7 @@ import System.IO ( BufferMode(LineBuffering)
, hSetBuffering
)
import System.IO.Error
import System.IO.Unsafe
import System.Posix.Files ( groupReadMode
, otherReadMode
, ownerReadMode
@ -74,15 +77,12 @@ import System.Posix.IO ( OpenFileFlags(exclusive)
, fdWrite
, openFd
)
import System.IO.Unsafe
load Absolute ["laminarc", "nix-store"]
data JobResult = Success | Failure deriving (Show, Read, Eq, Ord, Enum)
data ReportLevel = None | Self | Children deriving (Show, Eq, Ord, Enum)
newtype JobException = JobException Text deriving (Show, Exception)
throw = throwIO . JobException
newtype WaitException = WaitException Text deriving (Show, Exception)
@ -99,11 +99,6 @@ instance ExecArg Text where
asArg = asArg . toString
asArgFromList = asArgFromList . fmap toString
whenSelf level = when (level >= Self)
whenChildren level = when (level >= Children)
levelPrec Children = Self
levelPrec _ = None
drvBasename derivationName =
fromMaybe derivationName . viaNonEmpty last $ splitOn "/" derivationName
@ -115,9 +110,12 @@ runningPath, resultPath :: Text -> String
runningPath p = [i|#{runningDir}/#{drvBasename p}|]
resultPath p = [i|#{resultDir}/#{drvBasename p}|]
{-# NOINLINE depMap #-}
depMap :: TVar (Map Text (Seq Text))
depMap = unsafePerformIO $ newTVarIO mempty
{-# NOINLINE jobMap #-}
data BuildState = Pending | Running | Complete deriving (Show, Eq)
-- True means job is finished
jobMap :: TVar (Map Text (TVar BuildState))
jobMap = unsafePerformIO $ newTVarIO mempty
-- Bool means derivation itself needs to be build
getDependenciesFromNix :: Text -> IO (Seq Text)
@ -134,11 +132,8 @@ needsBuild derivationName = do
nixStoreRealiseDryRun :: Text -> IO (Seq Text)
nixStoreRealiseDryRun derivationName = do
maybeDeps <- Map.lookup derivationName <$> readTVarIO depMap
deps <- maybe (process
<$> (nix_store "-r" derivationName "--dry-run" &!> StdOut |> captureTrim)) pure maybeDeps
whenNothing_ maybeDeps $ atomically $ modifyTVar' depMap (Map.insert derivationName deps)
pure deps
process
<$> (nix_store "-r" derivationName "--dry-run" &!> StdOut |> captureTrim)
where
process =
fromList
@ -163,7 +158,6 @@ job derivationName = do
createDirectoryIfMissing True resultDir
writeFileText (resultPath derivationName) (show result)
removeFile (runningPath derivationName)
ensureDeps Children derivationName
unlessM (needsBuild derivationName) $ do
setResult Success
say [i|Build for #{derivationName} had already happened.|]
@ -182,13 +176,11 @@ job derivationName = do
nixStoreRealise :: Text -> [Text] -> IO ()
nixStoreRealise name flags = nix_store (["-r", name] <> flags)
ensureDeps :: ReportLevel -> Text -> IO ()
ensureDeps level derivationName = do
ensureDeps :: Text -> IO ()
ensureDeps derivationName = do
dependencies <- getDependenciesFromNix derivationName
whenChildren level $ forM_ dependencies $ \dep -> say [i|Requiring #{dep}.|]
forConcurrently_ dependencies (realise $ levelPrec level)
`catch` \(JobException e) ->
throw [i|#{e}\nFailed dependency for #{derivationName}|]
forConcurrently_ dependencies realise `catch` \(JobException e) ->
throw [i|#{e}\nFailed dependency for #{derivationName}|]
-- Nothing means failing to acquire lock on the derivation name for starting the job.
tryQueue :: Text -> IO (Maybe Text)
@ -223,14 +215,25 @@ tryQueue derivationName = handleExisting $ do
defaultMode =
ownerReadMode .|. ownerWriteMode .|. groupReadMode .|. otherReadMode
queueJobWithLaminarc :: ReportLevel -> Text -> IO Text
queueJobWithLaminarc level derivationName =
whenNothingM (tryQueue derivationName) (ensureRunningJob level derivationName)
queueJobWithLaminarc :: Text -> IO Text
queueJobWithLaminarc derivationName = whenNothingM
(do
jobMay <- tryQueue derivationName
whenJust jobMay $ \jobName ->
say [i|Job #{jobName} started for #{derivationName}. Waiting ...|]
pure jobMay
)
(ensureRunningJob derivationName)
ensureRunningJob :: ReportLevel -> Text -> IO Text
ensureRunningJob level derivationName = whenNothingM
(getRunningJob derivationName)
(queueJobWithLaminarc level derivationName)
ensureRunningJob :: Text -> IO Text
ensureRunningJob derivationName = whenNothingM
(do
jobMay <- getRunningJob derivationName
whenJust jobMay $ \jobName ->
say [i|Job #{jobName} running for #{derivationName}. Waiting ...|]
pure jobMay
)
(queueJobWithLaminarc derivationName)
-- Nothing means there is no running Job.
getRunningJob :: Text -> IO (Maybe Text)
@ -244,52 +247,84 @@ getRunningJob derivationName = poll 0
mayJob <- request
if count < 50 && mayJob == Just ""
then threadDelay 10000 >> poll (count + 1)
else pure mayJob
else do
realise :: ReportLevel -> Text -> IO ()
realise level derivationName = do
ensureDeps level derivationName
needBuild <- needsBuild derivationName
if needBuild
then runBuild
else whenSelf level $ say [i|#{derivationName} was already built.|]
pure mayJob
getJobVar :: Text -> IO (TVar BuildState)
getJobVar derivationName =
atomically
$ readTVar jobMap
>>= maybe makeVar pure
. Map.lookup derivationName
where
makeVar = do
newVar <- newTVar Pending
modifyTVar' jobMap (Map.insert derivationName newVar)
pure newVar
realise :: Text -> IO ()
realise derivationName = do
jobVar <- getJobVar derivationName
runHere <- atomically $ do
jobState <- readTVar jobVar
case jobState of
Complete -> pure False
Running -> retry
Pending -> do
writeTVar jobVar Running
pure True
when runHere $ do
say [i|Requiring #{derivationName}...|]
ensureDeps derivationName
needBuild <- needsBuild derivationName
if needBuild
then runBuild
else say [i|#{derivationName} was already built.|]
atomically $ writeTVar jobVar Complete
where
runBuild = do
jobName <- ensureRunningJob level derivationName
whenSelf level
$ say [i|Job #{jobName} running for #{derivationName}. Waiting ...|]
jobName <- ensureRunningJob derivationName
handleWaitFail $ waitForJob derivationName >>= \case
Success ->
whenSelf level $ say [i|Job #{jobName} completed #{derivationName}.|]
Success -> say [i|Job #{jobName} completed #{derivationName}.|]
Failure -> throw [i|Job #{jobName} failed #{derivationName}.|]
processWaitFail (WaitException e) = do
whenSelf level
$ sayErr
[i|Retrying to find or create a job for #{derivationName} after waiting for job failed with error "#{e}" |]
realise level derivationName
sayErr
[i|Retrying to find or create a job for #{derivationName} after waiting for job failed with error "#{e}" |]
realise derivationName
handleWaitFail = handle processWaitFail
checkStaleness :: Text -> IO ()
checkStaleness derivationName = forever $ do
whenJustM (getRunningJob derivationName) $ \jobName ->
handleJust (guard . isDoesNotExistError) (const pass) $ do
nothingQueued <-
T.null . decodeUtf8 <$> (laminarc "show-queued" |> captureTrim)
checkStaleness :: IO ()
checkStaleness = forever $ do
handleJust (guard . isDoesNotExistError) (const pass) $ do
nothingQueued <-
T.null . decodeUtf8 <$> (laminarc "show-queued" |> captureTrim)
when nothingQueued $ do
knownJobs <-
fmap strip
. lines
. decodeUtf8
<$> (laminarc "show-running" |> captureTrim)
now <- getCurrentTime
fileTime <- getModificationTime (runningPath derivationName)
let notRunning = not $ any (`isInfixOf` jobName) knownJobs
oldEnough = diffUTCTime now fileTime > 60
stale = notRunning && nothingQueued && oldEnough
when stale $ do
removeFile (runningPath derivationName)
throwWait
[i|File #{runningPath derivationName} claiming job name "#{jobName}" seems to be stale. Deleting File.|]
threadDelay 10000000
jobs <- Map.toList <$> readTVarIO jobMap
forConcurrently_ jobs $ \(derivationName, jobVar) ->
checkStalenessFor knownJobs jobVar derivationName
threadDelay 60000000
checkStalenessFor :: [Text] -> TVar BuildState -> Text -> IO ()
checkStalenessFor jobs jobVar derivationName =
whenM ((== Running) <$> readTVarIO jobVar)
$ whenJustM (getRunningJob derivationName)
$ \jobName -> do
say [i|Still waiting for job #{jobName} for #{derivationName}|]
now <- getCurrentTime
fileTime <- getModificationTime (runningPath derivationName)
let notRunning = not $ any (`isInfixOf` jobName) jobs
oldEnough = diffUTCTime now fileTime > 60
stale = notRunning && oldEnough
when stale $ do
removeFile (runningPath derivationName)
sayErr
[i|File #{runningPath derivationName} claiming job name "#{jobName}" seems to be stale. Deleting File.|]
waitForJob :: Text -> IO JobResult
waitForJob derivationName = do
@ -297,11 +332,8 @@ waitForJob derivationName = do
let finished = atomically (writeTVar done True)
withManager $ \manager -> do
_ <- watchDir manager runningDir fileDeleted (const finished)
withAsync
(whenNothingM_ (getRunningJob derivationName) finished)
(const $ race_ (atomically $ readTVar done >>= check)
(checkStaleness derivationName)
)
withAsync (whenNothingM_ (getRunningJob derivationName) finished)
(const $ atomically $ readTVar done >>= check)
resultText <-
handleJust
(guard . isDoesNotExistError)
@ -329,6 +361,7 @@ main = do
args <- fmap toText <$> getArgs
case args of
["realise-here", derivationName] -> job derivationName
["realise" , derivationName] -> realise Children derivationName
["realise", derivationName] ->
race_ (realise derivationName) checkStaleness
_ ->
sayErr "Usage: realise-here <derivationName> | realise <derivationName>"

View file

@ -36,10 +36,9 @@ let
checkout = ''
git clone git@hera.m-0.eu:nixos-config . --config advice.detachedHead=false
git checkout origin/$BRANCH
git show -q
REPODIR=.
'';
update-config =
"${pkgs.systemd}/bin/systemctl start --no-block update-config";
systems = [ "apollo" "hera" ];
homes = lib.attrNames (import ../../../home-manager/machines.nix);
mkHomeJob = (host: {
@ -69,7 +68,7 @@ let
'';
});
deployCommand = "${pkgs.writeShellScript "deploy-system-config"
"${pkgs.systemd}/bin/systemctl start update-config"}";
"${pkgs.systemd}/bin/systemctl start --no-block update-config"}";
in {
services.laminar.cfgFiles.jobs = {
"test-config.run" = pkgs.writeHaskell "test-config" {

View file

@ -9,7 +9,6 @@ let
(heading "ci.maralorn.de" "https://ci.maralorn.de")
(job "kassandra")
(job "test-config")
(job "bump-and-test-config")
(heading "haskell-taskwarrior"
"https://hackage.haskell.org/package/taskwarrior")
(badge "https://img.shields.io/hackage/v/taskwarrior.svg"

View file

@ -9,9 +9,9 @@ self: super: {
extra-system-pkgs = {
inherit (self.python3Packages) qrcode;
inherit (self)
git-crypt htop tree pwgen borgbackup inotifyTools direnv socat nmap ncdu
htop tree pwgen borgbackup inotifyTools direnv socat nmap ncdu
tcpdump tmux tig exa fzf ag fd bat ripgrep ranger pass sshuttle vnstat
entr libargon2 mblaze niv compsize mediainfo asciinema gomuks nix-output-monitor fdroidserver adoptopenjdk-jre-bin;
entr libargon2 mblaze niv compsize mediainfo asciinema gomuks nix-output-monitor fdroidserver;
};
my-home-pkgs = {