at master 96 lines 3.4 kB view raw
1#!/usr/bin/env nix-shell 2#!nix-shell -i runhaskell --packages 'haskellPackages.ghcWithPackages (ps: [ps.aeson ps.aeson-pretty ps.directory ps.process ps.optparse-applicative])' 3 4{-# LANGUAGE OverloadedStrings #-} 5{-# LANGUAGE RecordWildCards #-} 6 7module Main where 8 9import Options.Applicative 10import System.FilePath (takeDirectory, (</>)) 11import System.Process (readProcess) 12import Data.Aeson (object, (.=)) 13import Data.Aeson.Encode.Pretty (encodePretty', Config(..), defConfig, Indent(..), keyOrder) 14import qualified Data.ByteString.Lazy.Char8 as BL 15import qualified Data.Map.Strict as Map 16import Control.Monad (forM) 17import qualified Data.Text as T 18 19data Options = Options 20 { scriptPath :: FilePath 21 , channel :: String 22 } 23 24optionsParser :: Parser Options 25optionsParser = Options 26 <$> argument str 27 ( metavar "SCRIPT_PATH" 28 <> help "The path to the script" ) 29 <*> argument channelReader 30 ( metavar "CHANNEL" 31 <> help "The release channel (main or stable)" ) 32 33channelReader :: ReadM String 34channelReader = eitherReader $ \arg -> 35 if arg `elem` ["main", "stable"] 36 then Right arg 37 else Left "CHANNEL must be one of: main, stable" 38 39-- Custom configuration for pretty-printing JSON 40prettyConfig :: Config 41prettyConfig = defConfig 42 { confIndent = Spaces 2 43 , confCompare = keyOrder ["archMap", "fetchurlAttrSet", "platformList", "version"] 44 } 45 46main :: IO () 47main = do 48 let opts = info (optionsParser <**> helper) 49 ( fullDesc 50 <> progDesc "Updates the sources-{main|stable}.json files based on the upstream release channel" 51 <> header "update.hs - Haskell script with argument parsing" ) 52 53 -- Parse the command-line arguments 54 Options {..} <- execParser opts 55 56 -- Process the arguments 57 let scriptDir = takeDirectory scriptPath 58 let outputFile = scriptDir </> ("sources-" ++ channel ++ ".json") 59 60 -- Fetch current version 61 let baseUrl = "https://cli.upbound.io/" ++ channel 62 currentVersion <- readProcess "curl" ["-s", baseUrl ++ "/current/version"] "" 63 let version = filter (\x -> x /= 'v' && x /= '\n') currentVersion -- Remove the leading 'v' and the new line char 64 65 -- Architecture mapping 66 let archMapping = Map.fromList 67 [ ("aarch64-darwin", "darwin_arm64") 68 , ("x86_64-darwin", "darwin_amd64") 69 , ("aarch64-linux", "linux_arm64") 70 , ("x86_64-linux", "linux_amd64") 71 ] 72 73 -- Build platformList 74 let platformList = Map.keys archMapping 75 76 -- Build fetchurlAttrSet 77 fetchurlAttrSet <- fmap Map.fromList $ forM ["docker-credential-up", "up"] $ \cmd -> do 78 attrs <- forM (Map.toList archMapping) $ \(key, arch) -> do 79 let url = baseUrl ++ "/v" ++ version ++ "/bundle/" ++ cmd ++ "/" ++ arch ++ ".tar.gz" 80 _hash <- readProcess "nix-prefetch-url" [url] "" 81 let hash = T.unpack $ T.strip $ T.pack _hash 82 _sha256Hash <- readProcess "nix" ["hash", "convert", hash, "--hash-algo", "sha256"] "" 83 let sha256Hash = T.unpack $ T.strip $ T.pack _sha256Hash 84 return (key, object ["hash" .= sha256Hash, "url" .= url]) 85 return (cmd, object attrs) 86 87 -- Write output to JSON 88 let output = object 89 [ "version" .= version 90 , "platformList" .= platformList 91 , "archMap" .= archMapping 92 , "fetchurlAttrSet" .= fetchurlAttrSet 93 ] 94 BL.writeFile outputFile $ BL.snoc (encodePretty' prettyConfig output) '\n' 95 96 putStrLn $ "Output written to: " ++ outputFile