nixpkgs-update/app/Main.hs
2024-04-28 10:25:40 +10:00

174 lines
6.0 KiB
Haskell

{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
module Main where
import Control.Applicative ((<**>))
import qualified Data.Text as T
import qualified Data.Text.IO as T
import DeleteMerged (deleteDone)
import Git
import qualified GitHub as GH
import NVD (withVulnDB)
import qualified Nix
import qualified Options.Applicative as O
import OurPrelude
import qualified Repology
import System.IO (BufferMode (..), hSetBuffering, stderr, stdout)
import qualified System.Posix.Env as P
import Update (cveAll, cveReport, sourceGithubAll, updatePackage)
import Utils (Options (..), UpdateEnv (..), getGithubToken, getGithubUser)
default (T.Text)
data UpdateOptions = UpdateOptions
{ pr :: Bool,
cve :: Bool,
nixpkgsReview :: Bool,
outpaths :: Bool,
attrpathOpt :: Bool
}
data Command
= Update UpdateOptions Text
| UpdateBatch UpdateOptions Text
| DeleteDone Bool
| Version
| UpdateVulnDB
| CheckAllVulnerable
| SourceGithub
| FetchRepology
| CheckVulnerable Text Text Text
updateOptionsParser :: O.Parser UpdateOptions
updateOptionsParser =
UpdateOptions
<$> O.flag False True (O.long "pr" <> O.help "Make a pull request using Hub.")
<*> O.flag False True (O.long "cve" <> O.help "Make a CVE vulnerability report.")
<*> O.flag False True (O.long "nixpkgs-review" <> O.help "Runs nixpkgs-review on update commit rev")
<*> O.flag False True (O.long "outpaths" <> O.help "Calculate outpaths to determine the branch to target")
<*> O.flag False True (O.long "attrpath" <> O.help "UPDATE_INFO uses the exact attrpath.")
updateParser :: O.Parser Command
updateParser =
Update
<$> updateOptionsParser
<*> O.strArgument (O.metavar "UPDATE_INFO" <> O.help "update string of the form: 'pkg oldVer newVer update-page'\n\n example: 'tflint 0.15.0 0.15.1 repology.org'")
updateBatchParser :: O.Parser Command
updateBatchParser =
UpdateBatch
<$> updateOptionsParser
<*> O.strArgument (O.metavar "UPDATE_INFO" <> O.help "update string of the form: 'pkg oldVer newVer update-page'\n\n example: 'tflint 0.15.0 0.15.1 repology.org'")
deleteDoneParser :: O.Parser Command
deleteDoneParser =
DeleteDone
<$> O.flag False True (O.long "delete" <> O.help "Actually delete the done branches. Otherwise just prints the branches to delete.")
commandParser :: O.Parser Command
commandParser =
O.hsubparser
( O.command
"update"
(O.info (updateParser) (O.progDesc "Update one package"))
<> O.command
"update-batch"
(O.info (updateBatchParser) (O.progDesc "Update one package in batch mode."))
<> O.command
"delete-done"
( O.info
deleteDoneParser
(O.progDesc "Deletes branches from PRs that were merged or closed")
)
<> O.command
"version"
( O.info
(pure Version)
( O.progDesc
"Displays version information for nixpkgs-update and dependencies"
)
)
<> O.command
"update-vulnerability-db"
( O.info
(pure UpdateVulnDB)
(O.progDesc "Updates the vulnerability database")
)
<> O.command
"check-vulnerable"
(O.info checkVulnerable (O.progDesc "checks if something is vulnerable"))
<> O.command
"check-all-vulnerable"
( O.info
(pure CheckAllVulnerable)
(O.progDesc "checks all packages to update for vulnerabilities")
)
<> O.command
"source-github"
(O.info (pure SourceGithub) (O.progDesc "looks for updates on GitHub"))
<> O.command
"fetch-repology"
(O.info (pure FetchRepology) (O.progDesc "fetches update from Repology and prints them to stdout"))
)
checkVulnerable :: O.Parser Command
checkVulnerable =
CheckVulnerable
<$> O.strArgument (O.metavar "PRODUCT_ID")
<*> O.strArgument (O.metavar "OLD_VERSION")
<*> O.strArgument (O.metavar "NEW_VERSION")
programInfo :: O.ParserInfo Command
programInfo =
O.info
(commandParser <**> O.helper)
( O.fullDesc
<> O.progDesc "Update packages in the Nixpkgs repository"
<> O.header "nixpkgs-update"
)
main :: IO ()
main = do
hSetBuffering stdout LineBuffering
hSetBuffering stderr LineBuffering
command <- O.execParser programInfo
ghUser <- getGithubUser
token <- fromMaybe "" <$> getGithubToken
P.setEnv "GITHUB_TOKEN" (T.unpack token) True
P.setEnv "GITHUB_API_TOKEN" (T.unpack token) True
P.setEnv "PAGER" "" True
case command of
DeleteDone delete -> do
setupNixpkgs $ GH.untagName ghUser
deleteDone delete token ghUser
Update UpdateOptions {pr, cve, nixpkgsReview, outpaths, attrpathOpt} update -> do
setupNixpkgs $ GH.untagName ghUser
updatePackage (Options pr False ghUser token cve nixpkgsReview outpaths attrpathOpt) update
UpdateBatch UpdateOptions {pr, cve, nixpkgsReview, outpaths, attrpathOpt} update -> do
setupNixpkgs $ GH.untagName ghUser
updatePackage (Options pr True ghUser token cve nixpkgsReview outpaths attrpathOpt) update
Version -> do
v <- runExceptT Nix.version
case v of
Left t -> T.putStrLn ("error:" <> t)
Right t -> T.putStrLn t
UpdateVulnDB -> withVulnDB $ \_conn -> pure ()
CheckAllVulnerable -> do
setupNixpkgs $ GH.untagName ghUser
updates <- T.readFile "packages-to-update.txt"
cveAll undefined updates
CheckVulnerable productID oldVersion newVersion -> do
setupNixpkgs $ GH.untagName ghUser
report <-
cveReport
(UpdateEnv productID oldVersion newVersion Nothing (Options False False ghUser token False False False False))
T.putStrLn report
SourceGithub -> do
updates <- T.readFile "packages-to-update.txt"
setupNixpkgs $ GH.untagName ghUser
sourceGithubAll (Options False False ghUser token False False False False) updates
FetchRepology -> Repology.fetch