mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
Support split release artifactory, improve missing connection errors (#18271)
* Add resolution via artifactory, handle HTTP errors * Replace origin with wrapErr in resolveReleaseVersionUnsafe * Handle broken connections (e.g. no internet) * drop comment, fix foldMap id to fold * remove debugging writeFile calls run-all-tests: true * Rename partial field damlPath to damlPathUnsafe and add safe function * support multiple possible installation locations * update alternatives * Wrap CouldNotResolveReleaseVersion into AssistantError in unsafe resolve
This commit is contained in:
parent
b0006c84d6
commit
74a9d98a1f
@ -93,7 +93,8 @@ import DA.Daml.Project.Types
|
|||||||
ProjectPath(..),
|
ProjectPath(..),
|
||||||
ProjectConfig,
|
ProjectConfig,
|
||||||
unsafeResolveReleaseVersion)
|
unsafeResolveReleaseVersion)
|
||||||
import DA.Daml.Assistant.Version (resolveReleaseVersion)
|
import DA.Daml.Assistant.Version (resolveReleaseVersionUnsafe)
|
||||||
|
import DA.Daml.Assistant.Util (wrapErr)
|
||||||
import qualified DA.Daml.Compiler.Repl as Repl
|
import qualified DA.Daml.Compiler.Repl as Repl
|
||||||
import DA.Daml.Compiler.DocTest (docTest)
|
import DA.Daml.Compiler.DocTest (docTest)
|
||||||
import DA.Daml.Desugar (desugar)
|
import DA.Daml.Desugar (desugar)
|
||||||
@ -921,7 +922,8 @@ installDepsAndInitPackageDb opts (InitPkgDb shouldInit) =
|
|||||||
then do
|
then do
|
||||||
damlPath <- getDamlPath
|
damlPath <- getDamlPath
|
||||||
damlEnv <- getDamlEnv damlPath (LookForProjectPath False)
|
damlEnv <- getDamlEnv damlPath (LookForProjectPath False)
|
||||||
resolveReleaseVersion (envUseCache damlEnv) pSdkVersion
|
wrapErr "installing dependencies and initializing package database" $
|
||||||
|
resolveReleaseVersionUnsafe (envUseCache damlEnv) pSdkVersion
|
||||||
else pure (unsafeResolveReleaseVersion pSdkVersion)
|
else pure (unsafeResolveReleaseVersion pSdkVersion)
|
||||||
installDependencies
|
installDependencies
|
||||||
(toNormalizedFilePath' projRoot)
|
(toNormalizedFilePath' projRoot)
|
||||||
@ -1613,7 +1615,8 @@ execDocTest opts scriptDar (ImportSource importSource) files =
|
|||||||
then do
|
then do
|
||||||
damlPath <- getDamlPath
|
damlPath <- getDamlPath
|
||||||
damlEnv <- getDamlEnv damlPath (LookForProjectPath False)
|
damlEnv <- getDamlEnv damlPath (LookForProjectPath False)
|
||||||
resolveReleaseVersion (envUseCache damlEnv) SdkVersion.Class.unresolvedBuiltinSdkVersion
|
wrapErr "running doc test" $
|
||||||
|
resolveReleaseVersionUnsafe (envUseCache damlEnv) SdkVersion.Class.unresolvedBuiltinSdkVersion
|
||||||
else pure (unsafeResolveReleaseVersion SdkVersion.Class.unresolvedBuiltinSdkVersion)
|
else pure (unsafeResolveReleaseVersion SdkVersion.Class.unresolvedBuiltinSdkVersion)
|
||||||
installDependencies "." opts releaseVersion [scriptDar] []
|
installDependencies "." opts releaseVersion [scriptDar] []
|
||||||
createProjectPackageDb "." opts mempty
|
createProjectPackageDb "." opts mempty
|
||||||
|
@ -67,6 +67,7 @@ da_haskell_library(
|
|||||||
"tls",
|
"tls",
|
||||||
"typed-process",
|
"typed-process",
|
||||||
"unix-compat",
|
"unix-compat",
|
||||||
|
"uri-encode",
|
||||||
"utf8-string",
|
"utf8-string",
|
||||||
"yaml",
|
"yaml",
|
||||||
] + (["Win32"] if is_windows else []),
|
] + (["Win32"] if is_windows else []),
|
||||||
|
@ -200,7 +200,7 @@ runCommand env@Env{..} = \case
|
|||||||
let useCache =
|
let useCache =
|
||||||
UseCache
|
UseCache
|
||||||
{ cachePath = envCachePath
|
{ cachePath = envCachePath
|
||||||
, damlPath = envDamlPath
|
, damlPathUnsafe = envDamlPath
|
||||||
, overrideTimeout = if vForceRefresh then Just (CacheTimeout 1) else Nothing
|
, overrideTimeout = if vForceRefresh then Just (CacheTimeout 1) else Nothing
|
||||||
}
|
}
|
||||||
installedVersionsE <- tryAssistant $ getInstalledSdkVersions envDamlPath
|
installedVersionsE <- tryAssistant $ getInstalledSdkVersions envDamlPath
|
||||||
@ -279,8 +279,8 @@ runCommand env@Env{..} = \case
|
|||||||
install options envDamlPath (envUseCache env) envProjectPath envDamlAssistantSdkVersion
|
install options envDamlPath (envUseCache env) envProjectPath envDamlAssistantSdkVersion
|
||||||
|
|
||||||
Builtin (Uninstall unresolvedVersion) -> do
|
Builtin (Uninstall unresolvedVersion) -> do
|
||||||
version <- resolveReleaseVersion (envUseCache env) unresolvedVersion
|
versionOrErr <- resolveReleaseVersion (envUseCache env) unresolvedVersion
|
||||||
uninstallVersion env version
|
uninstallVersion env versionOrErr
|
||||||
|
|
||||||
Builtin (Exec cmd args) -> do
|
Builtin (Exec cmd args) -> do
|
||||||
wrapErr "Running executable in daml environment." $ do
|
wrapErr "Running executable in daml environment." $ do
|
||||||
|
@ -6,6 +6,7 @@ module DA.Daml.Assistant.Cache
|
|||||||
( cacheAvailableSdkVersions
|
( cacheAvailableSdkVersions
|
||||||
, CacheAge (..)
|
, CacheAge (..)
|
||||||
, UseCache (..)
|
, UseCache (..)
|
||||||
|
, damlPath
|
||||||
, cacheWith
|
, cacheWith
|
||||||
, loadFromCacheWith
|
, loadFromCacheWith
|
||||||
, saveToCacheWith
|
, saveToCacheWith
|
||||||
@ -53,17 +54,21 @@ data UseCache
|
|||||||
= UseCache
|
= UseCache
|
||||||
{ overrideTimeout :: Maybe CacheTimeout
|
{ overrideTimeout :: Maybe CacheTimeout
|
||||||
, cachePath :: CachePath
|
, cachePath :: CachePath
|
||||||
, damlPath :: DamlPath
|
, damlPathUnsafe :: DamlPath
|
||||||
}
|
}
|
||||||
| DontUseCache
|
| DontUseCache
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
damlPath :: UseCache -> Maybe DamlPath
|
||||||
|
damlPath DontUseCache = Nothing
|
||||||
|
damlPath UseCache { damlPathUnsafe } = Just damlPathUnsafe
|
||||||
|
|
||||||
cacheAvailableSdkVersions
|
cacheAvailableSdkVersions
|
||||||
:: UseCache
|
:: UseCache
|
||||||
-> (Maybe [ReleaseVersion] -> IO [ReleaseVersion])
|
-> (Maybe [ReleaseVersion] -> IO [ReleaseVersion])
|
||||||
-> IO ([ReleaseVersion], CacheAge)
|
-> IO ([ReleaseVersion], CacheAge)
|
||||||
cacheAvailableSdkVersions DontUseCache getVersions = (, Fresh) <$> getVersions Nothing
|
cacheAvailableSdkVersions DontUseCache getVersions = (, Fresh) <$> getVersions Nothing
|
||||||
cacheAvailableSdkVersions UseCache { overrideTimeout, cachePath, damlPath } getVersions = do
|
cacheAvailableSdkVersions UseCache { overrideTimeout, cachePath, damlPathUnsafe = damlPath } getVersions = do
|
||||||
damlConfigE <- tryConfig $ readDamlConfig damlPath
|
damlConfigE <- tryConfig $ readDamlConfig damlPath
|
||||||
let configUpdateCheckM = join $ eitherToMaybe (queryDamlConfig ["update-check"] =<< damlConfigE)
|
let configUpdateCheckM = join $ eitherToMaybe (queryDamlConfig ["update-check"] =<< damlConfigE)
|
||||||
(neverRefresh, timeout)
|
(neverRefresh, timeout)
|
||||||
|
@ -50,7 +50,7 @@ envUseCache Env {..} =
|
|||||||
|
|
||||||
mkUseCache :: CachePath -> DamlPath -> UseCache
|
mkUseCache :: CachePath -> DamlPath -> UseCache
|
||||||
mkUseCache cachePath damlPath =
|
mkUseCache cachePath damlPath =
|
||||||
UseCache { cachePath, damlPath, overrideTimeout = Nothing }
|
UseCache { cachePath, damlPathUnsafe = damlPath, overrideTimeout = Nothing }
|
||||||
|
|
||||||
-- | (internal) Override function with environment variable
|
-- | (internal) Override function with environment variable
|
||||||
-- if it is available.
|
-- if it is available.
|
||||||
@ -108,7 +108,7 @@ getFreshStableSdkVersionForCheck useCache = do
|
|||||||
parsed <- requiredE
|
parsed <- requiredE
|
||||||
("Invalid value for environment variable " <> pack sdkVersionLatestEnvVar <> ".")
|
("Invalid value for environment variable " <> pack sdkVersionLatestEnvVar <> ".")
|
||||||
(parseVersion (pack value))
|
(parseVersion (pack value))
|
||||||
pure (Just <$> resolveReleaseVersion useCache parsed)
|
pure (Just <$> resolveReleaseVersionUnsafe useCache parsed)
|
||||||
|
|
||||||
-- | Determine the viability of running sdk commands in the environment.
|
-- | Determine the viability of running sdk commands in the environment.
|
||||||
-- Returns the first failing test's error message.
|
-- Returns the first failing test's error message.
|
||||||
@ -152,7 +152,7 @@ getDamlAssistantPathDefault (DamlPath damlPath) =
|
|||||||
getDamlAssistantSdkVersion :: UseCache -> IO (Maybe DamlAssistantSdkVersion)
|
getDamlAssistantSdkVersion :: UseCache -> IO (Maybe DamlAssistantSdkVersion)
|
||||||
getDamlAssistantSdkVersion useCache =
|
getDamlAssistantSdkVersion useCache =
|
||||||
overrideWithEnvVarMaybeIO damlAssistantVersionEnvVar pure
|
overrideWithEnvVarMaybeIO damlAssistantVersionEnvVar pure
|
||||||
(fmap (fmap DamlAssistantSdkVersion) . traverse (resolveReleaseVersion useCache) . parseVersion . pack)
|
(fmap (fmap DamlAssistantSdkVersion) . traverse (resolveReleaseVersionUnsafe useCache) . parseVersion . pack)
|
||||||
(fmap DamlAssistantSdkVersion <$> tryAssistantM (getAssistantSdkVersion useCache))
|
(fmap DamlAssistantSdkVersion <$> tryAssistantM (getAssistantSdkVersion useCache))
|
||||||
|
|
||||||
-- | Determine absolute path of daml home directory.
|
-- | Determine absolute path of daml home directory.
|
||||||
@ -223,14 +223,23 @@ getSdk :: UseCache
|
|||||||
-> IO (Maybe ReleaseVersion, Maybe SdkPath)
|
-> IO (Maybe ReleaseVersion, Maybe SdkPath)
|
||||||
getSdk useCache damlPath projectPathM =
|
getSdk useCache damlPath projectPathM =
|
||||||
wrapErr "Determining SDK version and path." $ do
|
wrapErr "Determining SDK version and path." $ do
|
||||||
|
releaseVersion <-
|
||||||
releaseVersion <- overrideWithEnvVarMaybeIO sdkVersionEnvVar pure (traverse (resolveReleaseVersion useCache) . parseVersion . pack) $ firstJustM id
|
let parseAndResolve =
|
||||||
[ maybeM (pure Nothing)
|
traverse (resolveReleaseVersionUnsafe useCache) .
|
||||||
(tryAssistantM . getReleaseVersionFromSdkPath useCache . SdkPath)
|
parseVersion .
|
||||||
(getEnv sdkPathEnvVar)
|
pack
|
||||||
, mapM (getSdkVersionFromProjectPath useCache) projectPathM
|
in
|
||||||
, tryAssistantM $ getDefaultSdkVersion damlPath
|
overrideWithEnvVarMaybeIO
|
||||||
]
|
sdkVersionEnvVar
|
||||||
|
pure
|
||||||
|
parseAndResolve $
|
||||||
|
firstJustM id
|
||||||
|
[ maybeM (pure Nothing)
|
||||||
|
(tryAssistantM . getReleaseVersionFromSdkPath useCache . SdkPath)
|
||||||
|
(getEnv sdkPathEnvVar)
|
||||||
|
, mapM (getSdkVersionFromProjectPath useCache) projectPathM
|
||||||
|
, tryAssistantM $ getDefaultSdkVersion damlPath
|
||||||
|
]
|
||||||
|
|
||||||
sdkPath <- overrideWithEnvVarMaybe @SomeException sdkPathEnvVar makeAbsolute (Right . SdkPath) $
|
sdkPath <- overrideWithEnvVarMaybe @SomeException sdkPathEnvVar makeAbsolute (Right . SdkPath) $
|
||||||
useInstalledPath damlPath releaseVersion
|
useInstalledPath damlPath releaseVersion
|
||||||
|
@ -22,7 +22,7 @@ import DA.Daml.Assistant.Util
|
|||||||
import qualified DA.Daml.Assistant.Version as DAVersion
|
import qualified DA.Daml.Assistant.Version as DAVersion
|
||||||
import DA.Daml.Assistant.Install.Path
|
import DA.Daml.Assistant.Install.Path
|
||||||
import DA.Daml.Assistant.Install.Completion
|
import DA.Daml.Assistant.Install.Completion
|
||||||
import DA.Daml.Assistant.Version (getLatestSdkSnapshotVersion, getLatestReleaseVersion, UseCache (..), resolveSdkVersionToRelease)
|
import DA.Daml.Assistant.Version (getLatestSdkSnapshotVersion, getLatestReleaseVersion, UseCache (..), resolveSdkVersionToRelease, CouldNotResolveReleaseVersion(..))
|
||||||
import DA.Daml.Assistant.Cache (CacheTimeout (..))
|
import DA.Daml.Assistant.Cache (CacheTimeout (..))
|
||||||
import DA.Daml.Project.Consts
|
import DA.Daml.Project.Consts
|
||||||
import DA.Daml.Project.Config
|
import DA.Daml.Project.Config
|
||||||
@ -52,6 +52,7 @@ import Options.Applicative.Extended (determineAuto)
|
|||||||
import qualified Data.SemVer as V
|
import qualified Data.SemVer as V
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import qualified Control.Exception
|
import qualified Control.Exception
|
||||||
|
import qualified Data.List.NonEmpty as NonEmpty
|
||||||
|
|
||||||
-- unix specific
|
-- unix specific
|
||||||
import System.PosixCompat.Types ( FileMode )
|
import System.PosixCompat.Types ( FileMode )
|
||||||
@ -371,19 +372,39 @@ httpInstall env@InstallEnv{targetVersionM = releaseVersion, ..} = do
|
|||||||
!firstEEVersion =
|
!firstEEVersion =
|
||||||
let verStr = "1.12.0-snapshot.20210312.6498.0.707c86aa"
|
let verStr = "1.12.0-snapshot.20210312.6498.0.707c86aa"
|
||||||
in either Control.Exception.throw id (unsafeParseOldReleaseVersion verStr)
|
in either Control.Exception.throw id (unsafeParseOldReleaseVersion verStr)
|
||||||
|
|
||||||
downloadLocation :: DAVersion.InstallLocation -> IO ()
|
downloadLocation :: DAVersion.InstallLocation -> IO ()
|
||||||
downloadLocation (DAVersion.HttpInstallLocation url headers) = do
|
downloadLocation (DAVersion.HttpInstallLocations (location NonEmpty.:| alternatives)) = do
|
||||||
request <- requiredAny "Failed to parse HTTPS request." $ parseRequest ("GET " <> unpack url)
|
installationSucceeded <- go location alternatives
|
||||||
withResponse (setRequestHeaders headers request) $ \response -> do
|
when (not installationSucceeded) $
|
||||||
when (getResponseStatusCode response /= 200) $
|
throwIO $ assistantError "Could not download release from any of the following locations: "
|
||||||
throwIO . assistantErrorBecause ("Failed to download release from " <> url <> ".")
|
where
|
||||||
. pack . show $ getResponseStatus response
|
go :: DAVersion.HttpInstallLocation -> [DAVersion.HttpInstallLocation] -> IO Bool
|
||||||
let totalSizeM = readMay . BS.UTF8.toString =<< headMay (getResponseHeader "Content-Length" response)
|
go location alternatives = do
|
||||||
extractAndInstall (fmap Just env)
|
location <- try (downloadHttpLocation location)
|
||||||
. maybe id (\s -> (.| observeProgress s)) totalSizeM
|
case location of
|
||||||
$ getResponseBody response
|
Left err@AssistantError {} -> do
|
||||||
|
hPutStrLn stderr $ displayException err
|
||||||
|
case alternatives of
|
||||||
|
[] -> pure False
|
||||||
|
(next:rest) -> go next rest
|
||||||
|
Right () -> pure True
|
||||||
|
|
||||||
|
downloadHttpLocation :: DAVersion.HttpInstallLocation -> IO ()
|
||||||
|
downloadHttpLocation (DAVersion.HttpInstallLocation url headers name) = do
|
||||||
|
hPutStrLn stderr $ "Trying to install version via HTTP from " <> T.unpack name
|
||||||
|
request <- requiredAny "Failed to parse HTTPS request." $ parseRequest ("GET " <> unpack url)
|
||||||
|
withResponse (setRequestHeaders headers request) $ \response -> do
|
||||||
|
when (getResponseStatusCode response /= 200) $
|
||||||
|
throwIO . assistantErrorBecause ("Failed to download release from " <> url <> ".")
|
||||||
|
. pack . show $ getResponseStatus response
|
||||||
|
let totalSizeM = readMay . BS.UTF8.toString =<< headMay (getResponseHeader "Content-Length" response)
|
||||||
|
extractAndInstall (fmap Just env)
|
||||||
|
. maybe id (\s -> (.| observeProgress s)) totalSizeM
|
||||||
|
$ getResponseBody response
|
||||||
downloadLocation (DAVersion.FileInstallLocation file) =
|
downloadLocation (DAVersion.FileInstallLocation file) =
|
||||||
extractAndInstall (fmap Just env) (sourceFileBS file)
|
extractAndInstall (fmap Just env) (sourceFileBS file)
|
||||||
|
|
||||||
observeProgress :: MonadResource m =>
|
observeProgress :: MonadResource m =>
|
||||||
Int -> ConduitT BS.ByteString BS.ByteString m ()
|
Int -> ConduitT BS.ByteString BS.ByteString m ()
|
||||||
observeProgress totalSize = do
|
observeProgress totalSize = do
|
||||||
@ -468,24 +489,26 @@ versionInstall env@InstallEnv{targetVersionM = version, ..} = withInstallLock en
|
|||||||
|
|
||||||
-- | Install the latest version of the SDK.
|
-- | Install the latest version of the SDK.
|
||||||
latestInstall :: InstallEnvWithoutVersion -> IO ()
|
latestInstall :: InstallEnvWithoutVersion -> IO ()
|
||||||
latestInstall env@InstallEnv{..} = do
|
latestInstall env@InstallEnv{..} =
|
||||||
version1 <- getLatestReleaseVersion useCache
|
wrapErr "Installing latest daml version" $ do
|
||||||
-- override the cache if it's older than 1 day, even if daml-config.yaml says otherwise
|
version1 <- getLatestReleaseVersion useCache
|
||||||
{ overrideTimeout = Just (CacheTimeout 86400)
|
-- override the cache if it's older than 1 day, even if daml-config.yaml says otherwise
|
||||||
}
|
{ overrideTimeout = Just (CacheTimeout 86400)
|
||||||
version2M <- if iSnapshots options
|
}
|
||||||
then tryAssistantM $ getLatestSdkSnapshotVersion useCache
|
version2M <- if iSnapshots options
|
||||||
else pure Nothing
|
then tryAssistantM $ getLatestSdkSnapshotVersion useCache
|
||||||
let version = maybe version1 (max version1) version2M
|
else pure Nothing
|
||||||
versionInstall env { targetVersionM = version }
|
let version = maybe version1 (max version1) version2M
|
||||||
|
versionInstall env { targetVersionM = version }
|
||||||
|
|
||||||
-- | Install the SDK version of the current project.
|
-- | Install the SDK version of the current project.
|
||||||
projectInstall :: InstallEnvWithoutVersion -> ProjectPath -> IO ()
|
projectInstall :: InstallEnvWithoutVersion -> ProjectPath -> IO ()
|
||||||
projectInstall env projectPath = do
|
projectInstall env projectPath = do
|
||||||
|
wrapErr "Installing daml version in project config (daml.yaml)" $ do
|
||||||
projectConfig <- readProjectConfig projectPath
|
projectConfig <- readProjectConfig projectPath
|
||||||
unresolvedVersionM <- fromRightM throwIO $ releaseVersionFromProjectConfig projectConfig
|
unresolvedVersionM <- fromRightM throwIO $ releaseVersionFromProjectConfig projectConfig
|
||||||
unresolvedVersion <- required "SDK version missing from project config (daml.yaml)." unresolvedVersionM
|
unresolvedVersion <- required "SDK version missing from project config (daml.yaml)." unresolvedVersionM
|
||||||
version <- DAVersion.resolveReleaseVersion (useCache env) unresolvedVersion
|
version <- DAVersion.resolveReleaseVersionUnsafe (useCache env) unresolvedVersion
|
||||||
versionInstall env { targetVersionM = version }
|
versionInstall env { targetVersionM = version }
|
||||||
|
|
||||||
-- | Determine whether the assistant should be installed.
|
-- | Determine whether the assistant should be installed.
|
||||||
@ -504,73 +527,77 @@ pattern RawInstallTarget_Latest = RawInstallTarget "latest"
|
|||||||
|
|
||||||
-- | Run install command.
|
-- | Run install command.
|
||||||
install :: InstallOptions -> DamlPath -> UseCache -> Maybe ProjectPath -> Maybe DamlAssistantSdkVersion -> IO ()
|
install :: InstallOptions -> DamlPath -> UseCache -> Maybe ProjectPath -> Maybe DamlAssistantSdkVersion -> IO ()
|
||||||
install options damlPath useCache projectPathM assistantVersion = do
|
install options damlPath useCache projectPathM assistantVersion =
|
||||||
when (unActivateInstall (iActivate options)) $
|
wrapErr "Running daml install command" $ do
|
||||||
hPutStr stderr . unlines $
|
when (unActivateInstall (iActivate options)) $
|
||||||
[ "WARNING: --activate is deprecated, use --install-assistant=yes instead."
|
hPutStr stderr . unlines $
|
||||||
, ""
|
[ "WARNING: --activate is deprecated, use --install-assistant=yes instead."
|
||||||
]
|
|
||||||
|
|
||||||
missingAssistant <- not <$> doesFileExist (installedAssistantPath damlPath)
|
|
||||||
execPath <- getExecutablePath
|
|
||||||
damlConfigE <- tryConfig $ readDamlConfig damlPath
|
|
||||||
let installingFromOutside = not $
|
|
||||||
isPrefixOf (unwrapDamlPath damlPath </> "") execPath
|
|
||||||
targetVersionM = () -- determined later
|
|
||||||
output = putStrLn -- Output install messages to stdout.
|
|
||||||
artifactoryApiKeyM = DAVersion.queryArtifactoryApiKey =<< eitherToMaybe damlConfigE
|
|
||||||
env = InstallEnv {..}
|
|
||||||
warnAboutAnyInstallFlags command = do
|
|
||||||
when (unInstallWithInternalVersion (iInstallWithInternalVersion options)) $
|
|
||||||
hPutStrLn stderr $ unlines
|
|
||||||
[ "WARNING: You have supplied --install-with-internal-version=yes, but `" <> command <> "` does not take that option."
|
|
||||||
]
|
|
||||||
case unInstallWithCustomVersion (iInstallWithCustomVersion options) of
|
|
||||||
Just customVersion ->
|
|
||||||
hPutStrLn stderr $ unlines
|
|
||||||
[ "WARNING: You have supplied --install-with-custom-version=" <> customVersion <> ", but `" <> command <> "` does not take that option."
|
|
||||||
]
|
|
||||||
Nothing -> pure ()
|
|
||||||
|
|
||||||
case iTargetM options of
|
|
||||||
Nothing -> do
|
|
||||||
hPutStrLn stderr $ unlines
|
|
||||||
[ "ERROR: daml install requires a target."
|
|
||||||
, ""
|
, ""
|
||||||
, "Available install targets:"
|
|
||||||
, " daml install latest Install the latest stable SDK version."
|
|
||||||
, " daml install project Install the project SDK version."
|
|
||||||
, " daml install VERSION Install a specific SDK version."
|
|
||||||
, " daml install PATH Install SDK from an SDK release tarball."
|
|
||||||
]
|
]
|
||||||
exitFailure
|
|
||||||
|
|
||||||
Just RawInstallTarget_Project -> do
|
missingAssistant <- not <$> doesFileExist (installedAssistantPath damlPath)
|
||||||
projectPath <- required "'daml install project' must be run from within a project."
|
execPath <- getExecutablePath
|
||||||
projectPathM
|
damlConfigE <- tryConfig $ readDamlConfig damlPath
|
||||||
warnAboutAnyInstallFlags "daml install project"
|
let installingFromOutside = not $
|
||||||
projectInstall env projectPath
|
isPrefixOf (unwrapDamlPath damlPath </> "") execPath
|
||||||
|
targetVersionM = () -- determined later
|
||||||
|
output = putStrLn -- Output install messages to stdout.
|
||||||
|
artifactoryApiKeyM = DAVersion.queryArtifactoryApiKey =<< eitherToMaybe damlConfigE
|
||||||
|
env = InstallEnv {..}
|
||||||
|
warnAboutAnyInstallFlags command = do
|
||||||
|
when (unInstallWithInternalVersion (iInstallWithInternalVersion options)) $
|
||||||
|
hPutStrLn stderr $ unlines
|
||||||
|
[ "WARNING: You have supplied --install-with-internal-version=yes, but `" <> command <> "` does not take that option."
|
||||||
|
]
|
||||||
|
case unInstallWithCustomVersion (iInstallWithCustomVersion options) of
|
||||||
|
Just customVersion ->
|
||||||
|
hPutStrLn stderr $ unlines
|
||||||
|
[ "WARNING: You have supplied --install-with-custom-version=" <> customVersion <> ", but `" <> command <> "` does not take that option."
|
||||||
|
]
|
||||||
|
Nothing -> pure ()
|
||||||
|
|
||||||
Just RawInstallTarget_Latest -> do
|
case iTargetM options of
|
||||||
warnAboutAnyInstallFlags "daml install latest"
|
Nothing -> do
|
||||||
latestInstall env
|
hPutStrLn stderr $ unlines
|
||||||
|
[ "ERROR: daml install requires a target."
|
||||||
|
, ""
|
||||||
|
, "Available install targets:"
|
||||||
|
, " daml install latest Install the latest stable SDK version."
|
||||||
|
, " daml install project Install the project SDK version."
|
||||||
|
, " daml install VERSION Install a specific SDK version."
|
||||||
|
, " daml install PATH Install SDK from an SDK release tarball."
|
||||||
|
]
|
||||||
|
exitFailure
|
||||||
|
|
||||||
Just (RawInstallTarget arg) | Right version <- parseVersion (pack arg) -> do
|
Just RawInstallTarget_Project -> do
|
||||||
warnAboutAnyInstallFlags "daml install <version>"
|
projectPath <- required "'daml install project' must be run from within a project."
|
||||||
releaseVersion <- DAVersion.resolveReleaseVersion useCache version
|
projectPathM
|
||||||
versionInstall env { targetVersionM = releaseVersion }
|
warnAboutAnyInstallFlags "daml install project"
|
||||||
|
projectInstall env projectPath
|
||||||
|
|
||||||
Just (RawInstallTarget arg) -> do
|
Just RawInstallTarget_Latest -> do
|
||||||
testD <- doesDirectoryExist arg
|
warnAboutAnyInstallFlags "daml install latest"
|
||||||
testF <- doesFileExist arg
|
latestInstall env
|
||||||
if testD || testF then
|
|
||||||
pathInstall env arg
|
Just (RawInstallTarget arg) | Right version <- parseVersion (pack arg) -> do
|
||||||
else
|
warnAboutAnyInstallFlags "daml install <version>"
|
||||||
throwIO (assistantErrorBecause "Invalid install target. Expected version, path, 'project' or 'latest'." ("target = " <> pack arg))
|
releaseVersion <- DAVersion.resolveReleaseVersionUnsafe useCache version
|
||||||
|
versionInstall env { targetVersionM = releaseVersion }
|
||||||
|
|
||||||
|
Just (RawInstallTarget arg) -> do
|
||||||
|
testD <- doesDirectoryExist arg
|
||||||
|
testF <- doesFileExist arg
|
||||||
|
if testD || testF then
|
||||||
|
pathInstall env arg
|
||||||
|
else
|
||||||
|
throwIO (assistantErrorBecause "Invalid install target. Expected version, path, 'project' or 'latest'." ("target = " <> pack arg))
|
||||||
|
|
||||||
-- | Uninstall a specific SDK version.
|
-- | Uninstall a specific SDK version.
|
||||||
uninstallVersion :: Env -> ReleaseVersion -> IO ()
|
uninstallVersion :: Env -> Either CouldNotResolveReleaseVersion ReleaseVersion -> IO ()
|
||||||
uninstallVersion Env{..} releaseVersion = wrapErr "Uninstalling SDK version." $ do
|
uninstallVersion Env{} (Left (CouldNotResolveReleaseVersion _ unresolvedVersion)) =
|
||||||
|
wrapErr "Uninstalling SDK version." $
|
||||||
|
throwErr ("SDK version " <> unresolvedReleaseVersionToText unresolvedVersion <> " is not installed.")
|
||||||
|
uninstallVersion Env{..} (Right releaseVersion) = wrapErr "Uninstalling SDK version." $ do
|
||||||
let (SdkPath path) = defaultSdkPath envDamlPath releaseVersion
|
let (SdkPath path) = defaultSdkPath envDamlPath releaseVersion
|
||||||
|
|
||||||
exists <- doesDirectoryExist path
|
exists <- doesDirectoryExist path
|
||||||
|
@ -22,26 +22,40 @@ throwErr msg = throwIO (assistantError msg)
|
|||||||
|
|
||||||
-- | Handle synchronous exceptions by wrapping them in an AssistantError,
|
-- | Handle synchronous exceptions by wrapping them in an AssistantError,
|
||||||
-- add context to any assistant errors that are missing context.
|
-- add context to any assistant errors that are missing context.
|
||||||
wrapErr :: Text -> IO a -> IO a
|
wrapErrG :: (Text -> SomeException -> AssistantError) -> Text -> IO a -> IO a
|
||||||
wrapErr ctx m = m `catches`
|
wrapErrG wrapSomeException ctx m = m `catches`
|
||||||
[ Handler $ throwIO @IO @ExitCode
|
[ Handler $ throwIO @IO @ExitCode
|
||||||
, Handler $ \ExitCodeException{eceExitCode} -> exitWith eceExitCode
|
, Handler $ \ExitCodeException{eceExitCode} -> exitWith eceExitCode
|
||||||
, Handler $ throwIO . addErrorContext
|
, Handler $ throwIO . addErrorContext
|
||||||
, Handler $ throwIO . wrapException
|
, Handler $ throwIO . wrapSomeException ctx
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
wrapException :: SomeException -> AssistantError
|
|
||||||
wrapException err =
|
|
||||||
AssistantError
|
|
||||||
{ errContext = Just ctx
|
|
||||||
, errMessage = Nothing
|
|
||||||
, errInternal = Just (pack (show err))
|
|
||||||
}
|
|
||||||
|
|
||||||
addErrorContext :: AssistantError -> AssistantError
|
addErrorContext :: AssistantError -> AssistantError
|
||||||
addErrorContext err =
|
addErrorContext err =
|
||||||
err { errContext = errContext err <|> Just ctx }
|
err { errContext = errContext err <|> Just ctx }
|
||||||
|
|
||||||
|
wrapErr :: Text -> IO a -> IO a
|
||||||
|
wrapErr = wrapErrG wrapSomeExceptionWithoutMsg
|
||||||
|
|
||||||
|
wrapSomeExceptionWithoutMsg :: Text -> SomeException -> AssistantError
|
||||||
|
wrapSomeExceptionWithoutMsg ctx err =
|
||||||
|
AssistantError
|
||||||
|
{ errContext = Just ctx
|
||||||
|
, errMessage = Nothing
|
||||||
|
, errInternal = Just (pack (show err))
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapErrDisplay :: Text -> IO a -> IO a
|
||||||
|
wrapErrDisplay = wrapErrG wrapSomeExceptionWithMsg
|
||||||
|
|
||||||
|
wrapSomeExceptionWithMsg :: Text -> SomeException -> AssistantError
|
||||||
|
wrapSomeExceptionWithMsg ctx err =
|
||||||
|
AssistantError
|
||||||
|
{ errContext = Just ctx
|
||||||
|
, errMessage = Just (pack (displayException err))
|
||||||
|
, errInternal = Just (pack (show err))
|
||||||
|
}
|
||||||
|
|
||||||
-- | Catch a config error.
|
-- | Catch a config error.
|
||||||
tryConfig :: IO t -> IO (Either ConfigError t)
|
tryConfig :: IO t -> IO (Either ConfigError t)
|
||||||
tryConfig = try
|
tryConfig = try
|
||||||
|
@ -20,6 +20,9 @@ module DA.Daml.Assistant.Version
|
|||||||
, UseCache (..)
|
, UseCache (..)
|
||||||
, freshMaximumOfVersions
|
, freshMaximumOfVersions
|
||||||
, resolveReleaseVersion
|
, resolveReleaseVersion
|
||||||
|
, resolveReleaseVersionUnsafe
|
||||||
|
, CouldNotResolveSdkVersion(..)
|
||||||
|
, CouldNotResolveReleaseVersion(..)
|
||||||
, resolveSdkVersionToRelease
|
, resolveSdkVersionToRelease
|
||||||
, githubVersionLocation
|
, githubVersionLocation
|
||||||
, artifactoryVersionLocation
|
, artifactoryVersionLocation
|
||||||
@ -28,8 +31,12 @@ module DA.Daml.Assistant.Version
|
|||||||
, ArtifactoryApiKey(..)
|
, ArtifactoryApiKey(..)
|
||||||
, alternateVersionLocation
|
, alternateVersionLocation
|
||||||
, InstallLocation(..)
|
, InstallLocation(..)
|
||||||
|
, HttpInstallLocation(..)
|
||||||
|
, resolveReleaseVersionFromArtifactory
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Network.URI.Encode
|
||||||
|
|
||||||
import DA.Daml.Assistant.Types
|
import DA.Daml.Assistant.Types
|
||||||
import DA.Daml.Assistant.Util
|
import DA.Daml.Assistant.Util
|
||||||
import DA.Daml.Assistant.Cache
|
import DA.Daml.Assistant.Cache
|
||||||
@ -37,6 +44,7 @@ import DA.Daml.Project.Config
|
|||||||
import DA.Daml.Project.Consts hiding (getDamlPath, getProjectPath)
|
import DA.Daml.Project.Consts hiding (getDamlPath, getProjectPath)
|
||||||
import System.Environment.Blank
|
import System.Environment.Blank
|
||||||
import Control.Exception.Safe
|
import Control.Exception.Safe
|
||||||
|
import Control.Exception (mapException)
|
||||||
import Control.Monad.Extra
|
import Control.Monad.Extra
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Aeson (FromJSON(..), eitherDecodeStrict')
|
import Data.Aeson (FromJSON(..), eitherDecodeStrict')
|
||||||
@ -48,6 +56,7 @@ import Network.HTTP.Simple
|
|||||||
import Network.HTTP.Client
|
import Network.HTTP.Client
|
||||||
( Request(responseTimeout)
|
( Request(responseTimeout)
|
||||||
, responseTimeoutMicro
|
, responseTimeoutMicro
|
||||||
|
, setQueryString
|
||||||
)
|
)
|
||||||
|
|
||||||
import Data.ByteString (ByteString)
|
import Data.ByteString (ByteString)
|
||||||
@ -56,6 +65,7 @@ import qualified Data.ByteString.Char8 as BSC
|
|||||||
import qualified Data.ByteString.UTF8 as BSU
|
import qualified Data.ByteString.UTF8 as BSU
|
||||||
import qualified Data.SemVer as V
|
import qualified Data.SemVer as V
|
||||||
import Data.Function ((&))
|
import Data.Function ((&))
|
||||||
|
import Data.Foldable (fold)
|
||||||
import Control.Lens (view)
|
import Control.Lens (view)
|
||||||
import System.Directory (listDirectory, doesFileExist)
|
import System.Directory (listDirectory, doesFileExist)
|
||||||
import System.FilePath ((</>))
|
import System.FilePath ((</>))
|
||||||
@ -64,6 +74,7 @@ import Data.Either.Extra (eitherToMaybe)
|
|||||||
|
|
||||||
import qualified Data.Map.Strict as M
|
import qualified Data.Map.Strict as M
|
||||||
import qualified Data.List.NonEmpty as NonEmpty
|
import qualified Data.List.NonEmpty as NonEmpty
|
||||||
|
import Data.List.NonEmpty (NonEmpty)
|
||||||
import qualified System.Info
|
import qualified System.Info
|
||||||
|
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
@ -107,8 +118,15 @@ getSdkVersionFromProjectPath useCache projectPath =
|
|||||||
requiredIO ("Failed to read SDK version from " <> pack projectConfigName) $ do
|
requiredIO ("Failed to read SDK version from " <> pack projectConfigName) $ do
|
||||||
configE <- tryConfig $ readProjectConfig projectPath
|
configE <- tryConfig $ readProjectConfig projectPath
|
||||||
case releaseVersionFromProjectConfig =<< configE of
|
case releaseVersionFromProjectConfig =<< configE of
|
||||||
Right (Just v) ->
|
Right (Just v) -> do
|
||||||
resolveReleaseVersion useCache v
|
resolvedVersionOrErr <- resolveReleaseVersion useCache v
|
||||||
|
case resolvedVersionOrErr of
|
||||||
|
Left resolveErr ->
|
||||||
|
throwIO $ assistantErrorDetails
|
||||||
|
("sdk-version field in " <> projectConfigName <> " is not a valid Daml version. Validating version from the internet failed.")
|
||||||
|
[("path", unwrapProjectPath projectPath </> projectConfigName)
|
||||||
|
,("internal", displayException resolveErr)]
|
||||||
|
Right version -> pure version
|
||||||
Left (ConfigFileInvalid _ raw) ->
|
Left (ConfigFileInvalid _ raw) ->
|
||||||
throwIO $ assistantErrorDetails
|
throwIO $ assistantErrorDetails
|
||||||
(projectConfigName <> " is an invalid YAML file")
|
(projectConfigName <> " is an invalid YAML file")
|
||||||
@ -213,9 +231,9 @@ getAvailableSdkSnapshotVersions useCache =
|
|||||||
|
|
||||||
-- | Find the first occurence of a version on Github, without the cache. Keep in
|
-- | Find the first occurence of a version on Github, without the cache. Keep in
|
||||||
-- mind that versions are not sorted.
|
-- mind that versions are not sorted.
|
||||||
findAvailableSdkSnapshotVersion :: DamlPath -> (ReleaseVersion -> Bool) -> IO (Maybe ReleaseVersion)
|
findAvailableSdkSnapshotVersion :: Maybe DamlPath -> (ReleaseVersion -> Bool) -> IO (Maybe ReleaseVersion)
|
||||||
findAvailableSdkSnapshotVersion damlPath pred =
|
findAvailableSdkSnapshotVersion damlPathMb pred =
|
||||||
getAvailableSdkSnapshotVersionsUncached damlPath >>= searchSnapshotsUntil pred
|
getAvailableSdkSnapshotVersionsUncached damlPathMb >>= searchSnapshotsUntil pred
|
||||||
|
|
||||||
data SnapshotsList = SnapshotsList
|
data SnapshotsList = SnapshotsList
|
||||||
{ versions :: IO [ReleaseVersion]
|
{ versions :: IO [ReleaseVersion]
|
||||||
@ -246,13 +264,17 @@ searchSnapshotsUntil pred SnapshotsList { versions, next } = do
|
|||||||
-- https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-the-latest-release
|
-- https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#get-the-latest-release
|
||||||
-- because it sorts by time of upload, so a minor version bump like 2.5.15 may
|
-- because it sorts by time of upload, so a minor version bump like 2.5.15 may
|
||||||
-- supersede 2.7.2 if the minor release on 2.5.12 was released later
|
-- supersede 2.7.2 if the minor release on 2.5.12 was released later
|
||||||
getAvailableSdkSnapshotVersionsUncached :: DamlPath -> IO SnapshotsList
|
getAvailableSdkSnapshotVersionsUncached :: Maybe DamlPath -> IO SnapshotsList
|
||||||
getAvailableSdkSnapshotVersionsUncached damlPath = do
|
getAvailableSdkSnapshotVersionsUncached damlPathMb = do
|
||||||
damlConfigE <- tryConfig (readDamlConfig damlPath)
|
let defaultReleasesEndpoint = "https://api.github.com/repos/digital-asset/daml/releases"
|
||||||
let releasesEndpoint =
|
releasesEndpoint <-
|
||||||
|
case damlPathMb of
|
||||||
|
Nothing -> pure defaultReleasesEndpoint
|
||||||
|
Just damlPath -> do
|
||||||
|
damlConfigE <- tryConfig (readDamlConfig damlPath)
|
||||||
case queryDamlConfig ["releases-endpoint"] =<< damlConfigE of
|
case queryDamlConfig ["releases-endpoint"] =<< damlConfigE of
|
||||||
Right (Just url) -> url
|
Right (Just url) -> pure url
|
||||||
_ -> "https://api.github.com/repos/digital-asset/daml/releases"
|
_ -> pure defaultReleasesEndpoint
|
||||||
case parseRequest releasesEndpoint of
|
case parseRequest releasesEndpoint of
|
||||||
Just _ -> requestReleasesSnapshotsList releasesEndpoint
|
Just _ -> requestReleasesSnapshotsList releasesEndpoint
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
@ -357,46 +379,66 @@ getLatestReleaseVersion :: UseCache -> IO ReleaseVersion
|
|||||||
getLatestReleaseVersion useCache =
|
getLatestReleaseVersion useCache =
|
||||||
maximumOfNonEmptyVersions (getAvailableReleaseVersions useCache)
|
maximumOfNonEmptyVersions (getAvailableReleaseVersions useCache)
|
||||||
|
|
||||||
data CouldNotResolveVersion
|
data CouldNotResolveReleaseVersion = CouldNotResolveReleaseVersion ResolveReleaseError UnresolvedReleaseVersion
|
||||||
= CouldNotResolveReleaseVersion UnresolvedReleaseVersion
|
deriving (Show, Eq)
|
||||||
| CouldNotResolveSdkVersion SdkVersion
|
|
||||||
deriving (Show, Eq, Ord)
|
|
||||||
|
|
||||||
instance Exception CouldNotResolveVersion where
|
instance Exception CouldNotResolveReleaseVersion where
|
||||||
displayException (CouldNotResolveReleaseVersion version) = "Could not resolve release version " <> T.unpack (V.toText (unwrapUnresolvedReleaseVersion version))
|
displayException (CouldNotResolveReleaseVersion githubReleaseError version) =
|
||||||
displayException (CouldNotResolveSdkVersion version) = "Could not resolve SDK version " <> T.unpack (V.toText (unwrapSdkVersion version)) <> " to a release version. Possible fix: `daml version --force-reload yes`?"
|
"Could not resolve release version " <> T.unpack (V.toText (unwrapUnresolvedReleaseVersion version)) <> " from the internet. Reason: " <> displayException githubReleaseError
|
||||||
|
|
||||||
resolveReleaseVersion :: HasCallStack => UseCache -> UnresolvedReleaseVersion -> IO ReleaseVersion
|
resolveReleaseVersion :: HasCallStack => UseCache -> UnresolvedReleaseVersion -> IO (Either CouldNotResolveReleaseVersion ReleaseVersion)
|
||||||
resolveReleaseVersion _ targetVersion | isHeadVersion targetVersion = pure headReleaseVersion
|
resolveReleaseVersion useCache unresolvedVersion = do
|
||||||
resolveReleaseVersion useCache targetVersion = do
|
try (resolveReleaseVersionInternal useCache unresolvedVersion)
|
||||||
mbResolved <- resolveReleaseVersionFromDamlPath (damlPath useCache) targetVersion
|
|
||||||
|
resolveReleaseVersionUnsafe :: HasCallStack => UseCache -> UnresolvedReleaseVersion -> IO ReleaseVersion
|
||||||
|
resolveReleaseVersionUnsafe useCache targetVersion = mapException handle $ resolveReleaseVersionInternal useCache targetVersion
|
||||||
|
where
|
||||||
|
handle :: CouldNotResolveReleaseVersion -> AssistantError
|
||||||
|
handle = wrapSomeExceptionWithMsg "Resolve SDK version from release version" . SomeException
|
||||||
|
|
||||||
|
resolveReleaseVersionInternal :: HasCallStack => UseCache -> UnresolvedReleaseVersion -> IO ReleaseVersion
|
||||||
|
resolveReleaseVersionInternal _ targetVersion | isHeadVersion targetVersion = pure headReleaseVersion
|
||||||
|
resolveReleaseVersionInternal useCache targetVersion = do
|
||||||
|
mbResolved <- traverse (\damlPath -> resolveReleaseVersionFromDamlPath damlPath targetVersion) (damlPath useCache)
|
||||||
case mbResolved of
|
case mbResolved of
|
||||||
Just resolved -> pure resolved
|
Just (Just resolved) -> pure resolved
|
||||||
Nothing -> do
|
_ -> do
|
||||||
let isTargetVersion version =
|
let isTargetVersion version =
|
||||||
unwrapUnresolvedReleaseVersion targetVersion == releaseVersionFromReleaseVersion version
|
unwrapUnresolvedReleaseVersion targetVersion == releaseVersionFromReleaseVersion version
|
||||||
(releaseVersions, _) <- getAvailableSdkSnapshotVersions useCache
|
(releaseVersions, _) <- getAvailableSdkSnapshotVersions useCache
|
||||||
case filter isTargetVersion releaseVersions of
|
case filter isTargetVersion releaseVersions of
|
||||||
(x:_) -> pure x
|
(x:_) -> pure x
|
||||||
[] -> do
|
[] -> do
|
||||||
releasedVersionE <- resolveReleaseVersionFromGithub targetVersion
|
artifactoryReleasedVersionE <- resolveReleaseVersionFromArtifactory (damlPath useCache) targetVersion
|
||||||
case releasedVersionE of
|
case artifactoryReleasedVersionE of
|
||||||
Left _ ->
|
Right (Just version) -> pure version
|
||||||
throwIO (CouldNotResolveReleaseVersion targetVersion)
|
Left err -> throwIO (CouldNotResolveReleaseVersion err targetVersion)
|
||||||
Right releasedVersion -> do
|
Right Nothing -> do
|
||||||
_ <- cacheAvailableSdkVersions useCache (\pre -> pure (releasedVersion : fromMaybe [] pre))
|
githubReleasedVersionE <- resolveReleaseVersionFromGithub targetVersion
|
||||||
pure releasedVersion
|
case githubReleasedVersionE of
|
||||||
|
Left githubReleaseError ->
|
||||||
|
throwIO (CouldNotResolveReleaseVersion githubReleaseError targetVersion)
|
||||||
|
Right releasedVersion -> do
|
||||||
|
_ <- cacheAvailableSdkVersions useCache (\pre -> pure (releasedVersion : fromMaybe [] pre))
|
||||||
|
pure releasedVersion
|
||||||
|
|
||||||
resolveSdkVersionToRelease :: UseCache -> SdkVersion -> IO (Either CouldNotResolveVersion ReleaseVersion)
|
data CouldNotResolveSdkVersion = CouldNotResolveSdkVersion SdkVersion
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance Exception CouldNotResolveSdkVersion where
|
||||||
|
displayException (CouldNotResolveSdkVersion version) =
|
||||||
|
"Could not resolve SDK version " <> T.unpack (V.toText (unwrapSdkVersion version)) <> " to a release version. Possible fix: `daml version --force-reload yes`?"
|
||||||
|
|
||||||
|
resolveSdkVersionToRelease :: UseCache -> SdkVersion -> IO (Either CouldNotResolveSdkVersion ReleaseVersion)
|
||||||
resolveSdkVersionToRelease _ targetVersion | isHeadVersion targetVersion = pure (Right headReleaseVersion)
|
resolveSdkVersionToRelease _ targetVersion | isHeadVersion targetVersion = pure (Right headReleaseVersion)
|
||||||
resolveSdkVersionToRelease useCache targetVersion = do
|
resolveSdkVersionToRelease useCache targetVersion = do
|
||||||
resolved <- resolveSdkVersionFromDamlPath (damlPath useCache) targetVersion
|
resolved <- traverse (\damlPath -> resolveSdkVersionFromDamlPath damlPath targetVersion) (damlPath useCache)
|
||||||
case resolved of
|
case resolved of
|
||||||
Just resolved -> pure (Right resolved)
|
Just (Just resolved) -> pure (Right resolved)
|
||||||
Nothing -> do
|
_ -> do
|
||||||
let isTargetVersion version =
|
let isTargetVersion version =
|
||||||
targetVersion == sdkVersionFromReleaseVersion version
|
targetVersion == sdkVersionFromReleaseVersion version
|
||||||
(releaseVersions, _) <- getAvailableSdkSnapshotVersions useCache
|
(releaseVersions, _age) <- getAvailableSdkSnapshotVersions useCache
|
||||||
case filter isTargetVersion releaseVersions of
|
case filter isTargetVersion releaseVersions of
|
||||||
(x:_) -> pure $ Right x
|
(x:_) -> pure $ Right x
|
||||||
[] -> pure $ Left $ CouldNotResolveSdkVersion targetVersion
|
[] -> pure $ Left $ CouldNotResolveSdkVersion targetVersion
|
||||||
@ -417,7 +459,7 @@ resolveSdkVersionFromDamlPath damlPath targetSdkVersion = do
|
|||||||
|
|
||||||
-- | Subset of the github release response that we care about
|
-- | Subset of the github release response that we care about
|
||||||
data GithubReleaseResponseSubset = GithubReleaseResponseSubset
|
data GithubReleaseResponseSubset = GithubReleaseResponseSubset
|
||||||
{ assetNames :: [T.Text] }
|
{ githubAssetNames :: [T.Text] }
|
||||||
|
|
||||||
instance FromJSON GithubReleaseResponseSubset where
|
instance FromJSON GithubReleaseResponseSubset where
|
||||||
-- Akin to `GithubReleaseResponseSubset . fmap name . assets` but lifted into a parser over json
|
-- Akin to `GithubReleaseResponseSubset . fmap name . assets` but lifted into a parser over json
|
||||||
@ -431,34 +473,108 @@ releaseResponseSubsetSdkVersion responseSubset =
|
|||||||
withoutExt <- T.stripSuffix "-linux.tar.gz" name
|
withoutExt <- T.stripSuffix "-linux.tar.gz" name
|
||||||
T.stripPrefix "daml-sdk-" withoutExt
|
T.stripPrefix "daml-sdk-" withoutExt
|
||||||
in
|
in
|
||||||
listToMaybe $ mapMaybe extractMatchingName (assetNames responseSubset)
|
listToMaybe $ mapMaybe extractMatchingName (githubAssetNames responseSubset)
|
||||||
|
|
||||||
data GithubReleaseError
|
data ResolveReleaseError
|
||||||
= FailedToFindLinuxSdkInRelease String
|
= FailedToFindLinuxSdkInRelease String
|
||||||
| Couldn'tParseSdkVersion String InvalidVersion
|
| Couldn'tParseSdkVersion String InvalidVersion
|
||||||
|
| Couldn'tParseJSON String
|
||||||
|
| Couldn'tConnect (Maybe Int) String
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
instance Exception GithubReleaseError where
|
instance Exception ResolveReleaseError where
|
||||||
displayException (FailedToFindLinuxSdkInRelease url) =
|
displayException (FailedToFindLinuxSdkInRelease url) =
|
||||||
"Couldn't find Linux SDK in release at url: '" <> url <> "'"
|
"Couldn't find Linux SDK in release at url: '" <> url <> "'"
|
||||||
displayException (Couldn'tParseSdkVersion url v) =
|
displayException (Couldn'tParseSdkVersion url v) =
|
||||||
"Couldn't parse SDK in release at url '" <> url <> "': " <> displayException v
|
"Couldn't parse SDK in release at url '" <> url <> "': " <> displayException v
|
||||||
|
displayException (Couldn'tParseJSON url) =
|
||||||
|
"Couldn't parse JSON from the response from url '" <> url <> "'"
|
||||||
|
displayException (Couldn'tConnect statusCode url) =
|
||||||
|
let statusCodeDescription =
|
||||||
|
case statusCode of
|
||||||
|
Nothing -> ""
|
||||||
|
Just statusCode -> ", got HTTP status code `" <> show statusCode <> "`"
|
||||||
|
in
|
||||||
|
"Couldn't connect successfully to '" <> url <> "'" <> statusCodeDescription
|
||||||
|
|
||||||
-- | Since ~2.8.snapshot, the "enterprise version" (the version the user inputs) and the daml sdk version (the version of the daml repo) can differ
|
-- | Since ~2.8.snapshot, the "daml version" (the version the user inputs) and
|
||||||
-- As such, we derive the latter via the github api `assets` endpoint, looking for a file matching the expected `daml-sdk-$VERSION-$OS.tar.gz`
|
-- the daml sdk version (the version of the daml repo) can differ
|
||||||
resolveReleaseVersionFromGithub :: UnresolvedReleaseVersion -> IO (Either GithubReleaseError ReleaseVersion)
|
-- As such, we derive the latter via the github api `assets` endpoint, looking
|
||||||
|
-- for a file matching the expected `daml-sdk-$VERSION-$OS.tar.gz`
|
||||||
|
resolveReleaseVersionFromGithub :: UnresolvedReleaseVersion -> IO (Either ResolveReleaseError ReleaseVersion)
|
||||||
resolveReleaseVersionFromGithub unresolvedVersion = do
|
resolveReleaseVersionFromGithub unresolvedVersion = do
|
||||||
let tag = T.unpack (rawVersionToTextWithV (unwrapUnresolvedReleaseVersion unresolvedVersion))
|
let tag = T.unpack (rawVersionToTextWithV (unwrapUnresolvedReleaseVersion unresolvedVersion))
|
||||||
url = "https://api.github.com/repos/digital-asset/daml/releases/tags/" <> tag
|
url = "https://api.github.com/repos/digital-asset/daml/releases/tags/" <> tag
|
||||||
req <- parseRequest url
|
req <- parseRequest url
|
||||||
res <- httpJSON $ setRequestHeaders [("User-Agent", "request")] req
|
resOrErr <- try $ httpJSONEither $ setRequestHeaders [("User-Agent", "request")] req
|
||||||
pure $
|
pure $
|
||||||
case releaseResponseSubsetSdkVersion (getResponseBody res) of
|
case resOrErr of
|
||||||
Nothing -> Left (FailedToFindLinuxSdkInRelease url)
|
Right res -> case releaseResponseSubsetSdkVersion <$> getResponseBody res of
|
||||||
Just sdkVersionStr ->
|
Right (Just sdkVersionStr) ->
|
||||||
case parseSdkVersion sdkVersionStr of
|
case parseSdkVersion sdkVersionStr of
|
||||||
Left issue -> Left (Couldn'tParseSdkVersion url issue)
|
Left issue -> Left (Couldn'tParseSdkVersion url issue)
|
||||||
Right sdkVersion -> Right (mkReleaseVersion unresolvedVersion sdkVersion)
|
Right sdkVersion -> Right (mkReleaseVersion unresolvedVersion sdkVersion)
|
||||||
|
Right Nothing -> Left (FailedToFindLinuxSdkInRelease url)
|
||||||
|
Left _err
|
||||||
|
| getResponseStatusCode res == 200 -> Left (Couldn'tParseJSON url)
|
||||||
|
| getResponseStatusCode res == 404 -> Left (FailedToFindLinuxSdkInRelease url)
|
||||||
|
| otherwise -> Left (Couldn'tConnect (Just (getResponseStatusCode res)) url)
|
||||||
|
Left SomeException{} -> Left (Couldn'tConnect Nothing url)
|
||||||
|
|
||||||
|
-- | Subset of the artifactory release response that we care about
|
||||||
|
data ArtifactoryReleaseResponseSubset = ArtifactoryReleaseResponseSubset
|
||||||
|
{ artifactoryFiles :: [T.Text] }
|
||||||
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
|
instance FromJSON ArtifactoryReleaseResponseSubset where
|
||||||
|
-- Akin to `ArtifactoryReleaseResponseSubset . fmap name . assets` but lifted into a parser over json
|
||||||
|
parseJSON = withObject "ArtifactoryReleaseResponse" $ \v ->
|
||||||
|
ArtifactoryReleaseResponseSubset <$> explicitParseField (listParser parseJSON) v "files"
|
||||||
|
|
||||||
|
artifactoryReleaseResponseSubsetSdkVersion :: ArtifactoryReleaseResponseSubset -> Maybe T.Text
|
||||||
|
artifactoryReleaseResponseSubsetSdkVersion responseSubset =
|
||||||
|
let extractMatchingName :: T.Text -> Maybe T.Text
|
||||||
|
extractMatchingName path = do
|
||||||
|
let name = T.takeWhileEnd (/= '/') path
|
||||||
|
withoutExt <- T.stripSuffix "-linux-ee.tar.gz" name
|
||||||
|
T.stripPrefix "daml-sdk-" withoutExt
|
||||||
|
in
|
||||||
|
listToMaybe $ mapMaybe extractMatchingName (artifactoryFiles responseSubset)
|
||||||
|
|
||||||
|
resolveReleaseVersionFromArtifactory :: Maybe DamlPath -> UnresolvedReleaseVersion -> IO (Either ResolveReleaseError (Maybe ReleaseVersion))
|
||||||
|
resolveReleaseVersionFromArtifactory Nothing _ = pure (Right Nothing) -- Without a daml path, there is no artifactory key
|
||||||
|
resolveReleaseVersionFromArtifactory (Just damlPath) unresolvedVersion = do
|
||||||
|
damlConfig <- tryConfig $ readDamlConfig damlPath
|
||||||
|
case queryArtifactoryApiKey <$> damlConfig of
|
||||||
|
Right (Just apiKey) -> do
|
||||||
|
let url = "https://digitalasset.jfrog.io/artifactory/api/search/pattern"
|
||||||
|
searchParam = fold [ "external-files:daml-enterprise/*/", encodeTextToBS $ unresolvedReleaseVersionToText unresolvedVersion, "/*" ]
|
||||||
|
req <- parseRequest url
|
||||||
|
resOrErr <- try $ httpJSONEither $
|
||||||
|
setRequestHeaders
|
||||||
|
[ ("User-Agent", "request")
|
||||||
|
, ("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))
|
||||||
|
] $
|
||||||
|
setQueryString
|
||||||
|
[ ("pattern", Just searchParam)
|
||||||
|
]
|
||||||
|
req
|
||||||
|
pure $
|
||||||
|
case resOrErr of
|
||||||
|
Right res ->
|
||||||
|
case artifactoryReleaseResponseSubsetSdkVersion <$> getResponseBody res of
|
||||||
|
Right (Just sdkVersionStr) ->
|
||||||
|
case parseSdkVersion sdkVersionStr of
|
||||||
|
Left issue -> Left (Couldn'tParseSdkVersion url issue)
|
||||||
|
Right sdkVersion -> Right (Just (mkReleaseVersion unresolvedVersion sdkVersion))
|
||||||
|
Right Nothing -> Left (FailedToFindLinuxSdkInRelease url)
|
||||||
|
Left _err
|
||||||
|
| getResponseStatusCode res == 200 -> Left (Couldn'tParseJSON url)
|
||||||
|
| getResponseStatusCode res == 404 -> Left (FailedToFindLinuxSdkInRelease url)
|
||||||
|
| otherwise -> Left (Couldn'tConnect (Just (getResponseStatusCode res)) url)
|
||||||
|
Left SomeException{} ->
|
||||||
|
Left (Couldn'tConnect Nothing url)
|
||||||
|
_ -> pure (Right Nothing)
|
||||||
|
|
||||||
-- | OS-specific part of the asset name.
|
-- | OS-specific part of the asset name.
|
||||||
osName :: Text
|
osName :: Text
|
||||||
@ -478,26 +594,52 @@ queryArtifactoryApiKey damlConfig =
|
|||||||
|
|
||||||
-- | Install location for particular version.
|
-- | Install location for particular version.
|
||||||
artifactoryVersionLocation :: ReleaseVersion -> ArtifactoryApiKey -> InstallLocation
|
artifactoryVersionLocation :: ReleaseVersion -> ArtifactoryApiKey -> InstallLocation
|
||||||
artifactoryVersionLocation releaseVersion apiKey = HttpInstallLocation
|
artifactoryVersionLocation releaseVersion apiKey =
|
||||||
{ ilUrl = T.concat
|
let textShow = T.pack . show
|
||||||
[ "https://digitalasset.jfrog.io/artifactory/sdk-ee/"
|
majorVersion = view V.major (releaseVersionFromReleaseVersion releaseVersion)
|
||||||
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
|
minorVersion = view V.minor (releaseVersionFromReleaseVersion releaseVersion)
|
||||||
, "/daml-sdk-"
|
in
|
||||||
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
|
HttpInstallLocations $
|
||||||
, "-"
|
HttpInstallLocation
|
||||||
, osName
|
{ hilUrl = T.concat
|
||||||
, "-ee.tar.gz"
|
[ "https://digitalasset.jfrog.io/artifactory/external-files/daml-enterprise/"
|
||||||
|
, textShow majorVersion <> "." <> textShow minorVersion
|
||||||
|
, "/"
|
||||||
|
, versionToText releaseVersion
|
||||||
|
, "/daml-sdk-"
|
||||||
|
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
|
||||||
|
, "-"
|
||||||
|
, osName
|
||||||
|
, "-ee.tar.gz"
|
||||||
|
]
|
||||||
|
, hilHeaders =
|
||||||
|
[("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))]
|
||||||
|
, hilAlternativeName = "Artifactory `external-files` repo"
|
||||||
|
}
|
||||||
|
NonEmpty.:|
|
||||||
|
[ HttpInstallLocation
|
||||||
|
{ hilUrl = T.concat
|
||||||
|
[ "https://digitalasset.jfrog.io/artifactory/sdk-ee/"
|
||||||
|
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
|
||||||
|
, "/daml-sdk-"
|
||||||
|
, sdkVersionToText (sdkVersionFromReleaseVersion releaseVersion)
|
||||||
|
, "-"
|
||||||
|
, osName
|
||||||
|
, "-ee.tar.gz"
|
||||||
|
]
|
||||||
|
, hilHeaders =
|
||||||
|
[("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))]
|
||||||
|
, hilAlternativeName = "Artifactory `sdk-ee` repo (legacy)"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
, ilHeaders =
|
|
||||||
[("X-JFrog-Art-Api", T.encodeUtf8 (unwrapArtifactoryApiKey apiKey))]
|
|
||||||
}
|
|
||||||
|
|
||||||
-- | Install location from Github for particular version.
|
-- | Install location from Github for particular version.
|
||||||
githubVersionLocation :: ReleaseVersion -> InstallLocation
|
githubVersionLocation :: ReleaseVersion -> InstallLocation
|
||||||
githubVersionLocation releaseVersion =
|
githubVersionLocation releaseVersion = HttpInstallLocations $ pure
|
||||||
HttpInstallLocation
|
HttpInstallLocation
|
||||||
{ ilUrl = renderVersionLocation releaseVersion "https://github.com/digital-asset/daml/releases/download"
|
{ hilUrl = renderVersionLocation releaseVersion "https://github.com/digital-asset/daml/releases/download"
|
||||||
, ilHeaders = []
|
, hilHeaders = []
|
||||||
|
, hilAlternativeName = "Github `daml` repo releases"
|
||||||
}
|
}
|
||||||
|
|
||||||
alternateVersionLocation :: ReleaseVersion -> Text -> IO (Either Text InstallLocation)
|
alternateVersionLocation :: ReleaseVersion -> Text -> IO (Either Text InstallLocation)
|
||||||
@ -509,7 +651,13 @@ alternateVersionLocation releaseVersion prefix = do
|
|||||||
pure $ if exists
|
pure $ if exists
|
||||||
then Right (FileInstallLocation (T.unpack location))
|
then Right (FileInstallLocation (T.unpack location))
|
||||||
else Left location
|
else Left location
|
||||||
Just _ -> pure (Right (HttpInstallLocation location []))
|
Just _ ->
|
||||||
|
pure $ Right $ HttpInstallLocations $ pure
|
||||||
|
HttpInstallLocation
|
||||||
|
{ hilUrl = location
|
||||||
|
, hilHeaders = []
|
||||||
|
, hilAlternativeName = "Alternative install location from daml config `" <> prefix <> "`"
|
||||||
|
}
|
||||||
|
|
||||||
-- | Install location for particular version.
|
-- | Install location for particular version.
|
||||||
renderVersionLocation :: ReleaseVersion -> Text -> Text
|
renderVersionLocation :: ReleaseVersion -> Text -> Text
|
||||||
@ -529,11 +677,17 @@ renderVersionLocation releaseVersion prefix =
|
|||||||
-- required to access that URL. For example:
|
-- required to access that URL. For example:
|
||||||
-- "https://github.com/digital-asset/daml/releases/download/v0.11.1/daml-sdk-0.11.1-macos.tar.gz"
|
-- "https://github.com/digital-asset/daml/releases/download/v0.11.1/daml-sdk-0.11.1-macos.tar.gz"
|
||||||
data InstallLocation
|
data InstallLocation
|
||||||
= HttpInstallLocation
|
= HttpInstallLocations
|
||||||
{ ilUrl :: Text
|
{ ilAlternatives :: NonEmpty HttpInstallLocation
|
||||||
, ilHeaders :: RequestHeaders
|
|
||||||
}
|
}
|
||||||
| FileInstallLocation
|
| FileInstallLocation
|
||||||
{ ilPath :: FilePath
|
{ ilPath :: FilePath
|
||||||
} deriving (Eq, Show)
|
}
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
data HttpInstallLocation = HttpInstallLocation
|
||||||
|
{ hilUrl :: Text
|
||||||
|
, hilHeaders :: RequestHeaders
|
||||||
|
, hilAlternativeName :: Text
|
||||||
|
}
|
||||||
|
deriving (Eq, Show)
|
||||||
|
@ -42,6 +42,7 @@ import DA.Daml.Project.Types
|
|||||||
import qualified DA.Daml.Project.Types as DATypes
|
import qualified DA.Daml.Project.Types as DATypes
|
||||||
import qualified DA.Daml.Assistant.Version as DAVersion
|
import qualified DA.Daml.Assistant.Version as DAVersion
|
||||||
import qualified DA.Daml.Assistant.Env as DAEnv
|
import qualified DA.Daml.Assistant.Env as DAEnv
|
||||||
|
import qualified DA.Daml.Assistant.Util as DAUtil
|
||||||
|
|
||||||
-- Version of the "@mojotech/json-type-validation" library we're using.
|
-- Version of the "@mojotech/json-type-validation" library we're using.
|
||||||
jtvVersion :: T.Text
|
jtvVersion :: T.Text
|
||||||
@ -131,7 +132,7 @@ main = do
|
|||||||
Left _ -> fail "Invalid SDK version"
|
Left _ -> fail "Invalid SDK version"
|
||||||
Right v -> do
|
Right v -> do
|
||||||
useCache <- DAEnv.mkUseCache <$> DAEnv.getCachePath <*> DAEnv.getDamlPath
|
useCache <- DAEnv.mkUseCache <$> DAEnv.getCachePath <*> DAEnv.getDamlPath
|
||||||
DAVersion.resolveReleaseVersion useCache v
|
DAUtil.wrapErr "Getting SDK version for codegen" $ DAVersion.resolveReleaseVersionUnsafe useCache v
|
||||||
pkgs <- readPackages optInputDars
|
pkgs <- readPackages optInputDars
|
||||||
case mergePackageMap pkgs of
|
case mergePackageMap pkgs of
|
||||||
Left err -> fail . T.unpack $ err
|
Left err -> fail . T.unpack $ err
|
||||||
|
@ -87,6 +87,9 @@ sdkVersionToText = V.toText . unwrapSdkVersion
|
|||||||
unresolvedReleaseVersionToString :: UnresolvedReleaseVersion -> String
|
unresolvedReleaseVersionToString :: UnresolvedReleaseVersion -> String
|
||||||
unresolvedReleaseVersionToString = V.toString . unwrapUnresolvedReleaseVersion
|
unresolvedReleaseVersionToString = V.toString . unwrapUnresolvedReleaseVersion
|
||||||
|
|
||||||
|
unresolvedReleaseVersionToText :: UnresolvedReleaseVersion -> Text
|
||||||
|
unresolvedReleaseVersionToText = V.toText . unwrapUnresolvedReleaseVersion
|
||||||
|
|
||||||
class IsVersion a where
|
class IsVersion a where
|
||||||
isHeadVersion :: a -> Bool
|
isHeadVersion :: a -> Bool
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user