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/on-my-machine.nix
./roles/headless.nix ./roles/headless.nix
./roles/weechat ./roles/weechat
./roles/kassandra-server.nix
./roles/headless-mpd.nix ./roles/headless-mpd.nix
./roles/mail.nix ./roles/mail.nix
./roles/mail2rss.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/coturn.nix
../../roles/go-neb.nix ../../roles/go-neb.nix
../../roles/laminar ../../roles/laminar
../../roles/kassandra-server.nix
./web.nix ./web.nix
./mail.nix ./mail.nix
./boot.nix ./boot.nix
@ -38,7 +39,9 @@ in {
''; '';
startAgent = true; startAgent = true;
}; };
java.enable = true;
}; };
nixpkgs.config.android_sdk.accept_license = true;
systemd.services."pg_backup" = { systemd.services."pg_backup" = {
script = let name = "matrix-synapse"; script = let name = "matrix-synapse";
in '' 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 let
path = [ pkgs.git pkgs.nix pkgs.gnutar pkgs.gzip pkgs.openssh pkgs.laminar ]; path = [ pkgs.git pkgs.nix pkgs.gnutar pkgs.gzip pkgs.openssh pkgs.laminar ];
setup = '' setup = ''
set -e
export PATH=${lib.makeBinPath path}:$PATH 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: '' target = name: ''
set -e
${setup} ${setup}
export HOME=$PWD export HOME=$PWD
git clone git@localhost:kassandra2 kassandra git clone git@localhost:kassandra2 .
cd kassandra
git show -q git show -q
echo "Evaluating nix-expression." echo "Evaluating nix-expression."
export FLAGS='--builders @/etc/nix/machines --max-jobs 1' export FLAGS='--builders @/etc/nix/machines --max-jobs 1'
@ -19,11 +31,19 @@ let
laminarc set "RESULTDRV=$drv" laminarc set "RESULTDRV=$drv"
''; '';
in { in {
security.sudo.extraRules = [{
commands = [{
command = deploy;
options = [ "NOPASSWD" ];
}];
users = [ "laminar" ];
}];
services.laminar.cfgFiles.jobs = { services.laminar.cfgFiles.jobs = {
"kassandra.run" = pkgs.writeShellScript "kassandra" '' "kassandra.run" = pkgs.writeShellScript "kassandra" ''
${setup} ${setup}
echo Launching and waiting for jobs lib, app, android and server echo Launching and waiting for jobs lib, app, android and server
laminarc run kassandra-lib kassandra-android kassandra-app kassandra-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-lib.run" = pkgs.writeShellScript "kassandra-lib" (target "lib");
"kassandra-app.run" = pkgs.writeShellScript "kassandra-app" (target "app"); "kassandra-app.run" = pkgs.writeShellScript "kassandra-app" (target "app");

View file

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

View file

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

View file

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

View file

@ -9,9 +9,9 @@ self: super: {
extra-system-pkgs = { extra-system-pkgs = {
inherit (self.python3Packages) qrcode; inherit (self.python3Packages) qrcode;
inherit (self) 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 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 = { my-home-pkgs = {