stackctl 1.3.0.1 → 1.3.0.2
raw patch · 8 files changed
+90/−49 lines, 8 files
Files
- CHANGELOG.md +6/−1
- src/Stackctl/AWS/CloudFormation.hs +10/−4
- src/Stackctl/AWS/Core.hs +5/−1
- src/Stackctl/AWS/Lambda.hs +3/−1
- src/Stackctl/Spec/Changes.hs +4/−1
- src/Stackctl/Spec/Changes/Format.hs +36/−18
- src/Stackctl/Spec/Deploy.hs +10/−7
- stackctl.cabal +16/−16
CHANGELOG.md view
@@ -1,4 +1,9 @@-## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.3.0.1...main)+## [_Unreleased_](https://github.com/freckle/stackctl/compare/v1.3.0.2...main)++## [v1.3.0.2](https://github.com/freckle/stackctl/compare/v1.3.0.1...v1.3.0.2)++- Adjust timeout when invoking Lambdas to allow up to Lambda's own execution+ timeout (15 minutes). ## [v1.3.0.1](https://github.com/freckle/stackctl/compare/v1.3.0.0...v1.3.0.1)
src/Stackctl/AWS/CloudFormation.hs view
@@ -2,10 +2,11 @@ ( Stack(..) , stack_stackName , stackDescription- , stackIsRollbackComplete+ , stackStatusRequiresDeletion , StackId(..) , StackName(..) , StackDescription(..)+ , StackStatus(..) , StackEvent(..) , ResourceStatus(..) , stackEvent_eventId@@ -479,9 +480,14 @@ stack ^. stack_stackStatus == StackStatus_REVIEW_IN_PROGRESS && isNothing (stack ^. stack_lastUpdatedTime) -stackIsRollbackComplete :: Stack -> Bool-stackIsRollbackComplete stack =- stack ^. stack_stackStatus == StackStatus_ROLLBACK_COMPLETE+stackStatusRequiresDeletion :: Stack -> Maybe StackStatus+stackStatusRequiresDeletion stack = status+ <$ guard (status `elem` requiresDeletionStatuses)+ where status = stack ^. stack_stackStatus++requiresDeletionStatuses :: [StackStatus]+requiresDeletionStatuses =+ [StackStatus_ROLLBACK_COMPLETE, StackStatus_ROLLBACK_FAILED] runningStatuses :: [StackStatus] runningStatuses =
src/Stackctl/AWS/Core.hs view
@@ -9,6 +9,7 @@ -- * Modifiers on 'AwsEnv' , awsWithin+ , awsTimeout -- * 'Amazonka' extensions , AccountId(..)@@ -20,7 +21,7 @@ , MonadResource ) where -import Stackctl.Prelude+import Stackctl.Prelude hiding (timeout) import Amazonka hiding (LogLevel(..)) import qualified Amazonka as AWS@@ -105,6 +106,9 @@ awsWithin :: (MonadReader env m, HasAwsEnv env) => Region -> m a -> m a awsWithin r = local $ over (awsEnvL . unL) (within r)++awsTimeout :: (MonadReader env m, HasAwsEnv env) => Seconds -> m a -> m a+awsTimeout t = local $ over (awsEnvL . unL) (timeout t) newtype AccountId = AccountId { unAccountId :: Text
src/Stackctl/AWS/Lambda.hs view
@@ -71,7 +71,9 @@ awsLambdaInvoke name payload = do logDebug $ "Invoking function" :# ["name" .= name] - resp <- awsSend $ newInvoke name $ BSL.toStrict $ encode payload+ -- Match Lambda's own limit (15 minutes) and add some buffer+ resp <- awsTimeout 905 $ awsSend $ newInvoke name $ BSL.toStrict $ encode+ payload let status = resp ^. invokeResponse_statusCode
src/Stackctl/Spec/Changes.hs view
@@ -24,6 +24,7 @@ data ChangesOptions = ChangesOptions { scoFormat :: Format+ , scoOmitFull :: OmitFull , scoParameters :: [Parameter] , scoTags :: [Tag] , scoOutput :: Maybe FilePath@@ -34,6 +35,7 @@ parseChangesOptions :: Parser ChangesOptions parseChangesOptions = ChangesOptions <$> formatOption+ <*> omitFullOption <*> many parameterOption <*> many tagOption <*> optional (argument str@@ -78,7 +80,8 @@ let name = pack $ stackSpecPathFilePath $ stackSpecSpecPath spec- formatted = formatChangeSet colors name scoFormat mChangeSet+ formatted =+ formatChangeSet colors scoOmitFull name scoFormat mChangeSet case scoOutput of Nothing -> pushLoggerLn formatted
src/Stackctl/Spec/Changes/Format.hs view
@@ -1,6 +1,8 @@ module Stackctl.Spec.Changes.Format ( Format(..) , formatOption+ , OmitFull(..)+ , omitFullOption , formatChangeSet , formatTTY ) where@@ -17,6 +19,10 @@ = FormatTTY | FormatPullRequest +data OmitFull+ = OmitFull+ | IncludeFull+ formatOption :: Parser Format formatOption = option (eitherReader readFormat) $ mconcat [ short 'f'@@ -37,10 +43,19 @@ FormatTTY -> "tty" FormatPullRequest -> "pr" -formatChangeSet :: Colors -> Text -> Format -> Maybe ChangeSet -> Text-formatChangeSet colors name = \case+-- brittany-disable-next-binding++omitFullOption :: Parser OmitFull+omitFullOption = flag IncludeFull OmitFull+ ( long "no-include-full"+ <> help "Don't include full ChangeSet JSON details"+ )++formatChangeSet+ :: Colors -> OmitFull -> Text -> Format -> Maybe ChangeSet -> Text+formatChangeSet colors omitFull name = \case FormatTTY -> formatTTY colors name- FormatPullRequest -> formatPullRequest name+ FormatPullRequest -> formatPullRequest omitFull name formatTTY :: Colors -> Text -> Maybe ChangeSet -> Text formatTTY colors@Colors {..} name mChangeSet = case (mChangeSet, rChanges) of@@ -83,15 +98,15 @@ x@Replacement_Conditional -> yellow (toText x) Replacement' x -> x -formatPullRequest :: Text -> Maybe ChangeSet -> Text-formatPullRequest name mChangeSet =+formatPullRequest :: OmitFull -> Text -> Maybe ChangeSet -> Text+formatPullRequest omitFull name mChangeSet = emoji <> " This PR generates " <> description <> " for `" <> name <> "`."- <> fromMaybe "" (commentBody <$> mChangeSet <*> rChanges)+ <> fromMaybe "" (commentBody omitFull <$> mChangeSet <*> rChanges) <> "\n" where emoji = case (mChangeSet, nChanges) of@@ -112,24 +127,27 @@ changes <- csChanges cs NE.nonEmpty $ mapMaybe resourceChange changes -commentBody :: ChangeSet -> NonEmpty ResourceChange -> Text-commentBody cs rcs =+commentBody :: OmitFull -> ChangeSet -> NonEmpty ResourceChange -> Text+commentBody omitFull cs rcs = mconcat $ [ "\n" , "\n| Action | Logical Id | Physical Id | Type | Replacement | Scope | Details |" , "\n| --- | --- | --- | --- | --- | --- | --- |" ] <> map commentTableRow (NE.toList rcs)- <> [ "\n"- , "\n<details>"- , "\n<summary>Full changes</summary>"- , "\n"- , "\n```json"- , "\n" <> changeSetJSON cs- , "\n```"- , "\n"- , "\n</details>"- ]+ <> case omitFull of+ OmitFull -> []+ IncludeFull ->+ [ "\n"+ , "\n<details>"+ , "\n<summary>Full changes</summary>"+ , "\n"+ , "\n```json"+ , "\n" <> changeSetJSON cs+ , "\n```"+ , "\n"+ , "\n</details>"+ ] commentTableRow :: ResourceChange -> Text commentTableRow ResourceChange' {..} = mconcat
src/Stackctl/Spec/Deploy.hs view
@@ -75,7 +75,8 @@ for_ specs $ \spec -> do withThreadContext ["stackName" .= stackSpecStackName spec] $ do- handleRollbackComplete sdoDeployConfirmation $ stackSpecStackName spec+ checkIfStackRequiresDeletion sdoDeployConfirmation+ $ stackSpecStackName spec emChangeSet <- createChangeSet spec sdoParameters sdoTags @@ -102,7 +103,7 @@ | DeployWithoutConfirmation deriving stock Eq -handleRollbackComplete+checkIfStackRequiresDeletion :: ( MonadUnliftIO m , MonadResource m , MonadLogger m@@ -113,13 +114,14 @@ => DeployConfirmation -> StackName -> m ()-handleRollbackComplete confirmation stackName = do+checkIfStackRequiresDeletion confirmation stackName = do mStack <- awsCloudFormationDescribeStackMaybe stackName - when (maybe False stackIsRollbackComplete mStack) $ do- logWarn- $ "Stack is in ROLLBACK_COMPLETE state and must be deleted before proceeding"- :# ["stackName" .= stackName]+ for_ (stackStatusRequiresDeletion =<< mStack) $ \status -> do+ logWarn $ "Stack must be deleted before proceeding" :# ["status" .= status]+ when (status == StackStatus_ROLLBACK_FAILED)+ $ logWarn+ "Stack is in ROLLBACK_FAILED. This may require elevated permissions for the delete to succeed" case confirmation of DeployWithConfirmation -> promptContinue@@ -127,6 +129,7 @@ logError "Refusing to delete without confirmation" exitFailure + logInfo "Deleting Stack" result <- awsCloudFormationDeleteStack stackName case result of
stackctl.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: stackctl-version: 1.3.0.1+version: 1.3.0.2 license: MIT license-file: LICENSE copyright: 2022 Renaissance Learning Inc@@ -72,11 +72,11 @@ TypeApplications TypeFamilies ghc-options:- -fwrite-ide-info -Weverything -Wno-all-missed-specialisations- -Wno-missing-import-lists -Wno-missing-kind-signatures- -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode- -Wno-prepositive-qualified-module -Wno-unsafe- -optP-Wno-nonportable-include-path+ -fignore-optim-changes -fwrite-ide-info -Weverything+ -Wno-all-missed-specialisations -Wno-missing-import-lists+ -Wno-missing-kind-signatures -Wno-missing-local-signatures+ -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module+ -Wno-unsafe -optP-Wno-nonportable-include-path build-depends: Blammo >=1.1.1.1,@@ -132,11 +132,11 @@ TypeApplications TypeFamilies ghc-options:- -fwrite-ide-info -Weverything -Wno-all-missed-specialisations- -Wno-missing-import-lists -Wno-missing-kind-signatures- -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode- -Wno-prepositive-qualified-module -Wno-unsafe- -optP-Wno-nonportable-include-path -threaded -rtsopts+ -fignore-optim-changes -fwrite-ide-info -Weverything+ -Wno-all-missed-specialisations -Wno-missing-import-lists+ -Wno-missing-kind-signatures -Wno-missing-local-signatures+ -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module+ -Wno-unsafe -optP-Wno-nonportable-include-path -threaded -rtsopts -with-rtsopts=-N build-depends:@@ -168,11 +168,11 @@ TypeApplications TypeFamilies ghc-options:- -fwrite-ide-info -Weverything -Wno-all-missed-specialisations- -Wno-missing-import-lists -Wno-missing-kind-signatures- -Wno-missing-local-signatures -Wno-missing-safe-haskell-mode- -Wno-prepositive-qualified-module -Wno-unsafe- -optP-Wno-nonportable-include-path+ -fignore-optim-changes -fwrite-ide-info -Weverything+ -Wno-all-missed-specialisations -Wno-missing-import-lists+ -Wno-missing-kind-signatures -Wno-missing-local-signatures+ -Wno-missing-safe-haskell-mode -Wno-prepositive-qualified-module+ -Wno-unsafe -optP-Wno-nonportable-include-path build-depends: QuickCheck,