brut 0.0.27 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/brutrb.com/.vitepress/config.mjs +1 -0
- data/brutrb.com/dev-environment.md +6 -5
- data/brutrb.com/doc-conventions.md +1 -1
- data/brutrb.com/getting-started.md +64 -28
- data/brutrb.com/instrumentation.md +12 -0
- data/brutrb.com/layouts.md +130 -0
- data/docs/404.html +2 -2
- data/docs/ai.html +5 -5
- data/docs/api/Brut/BackEnd/SeedData.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
- data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
- data/docs/api/Brut/BackEnd/Validators.html +1 -1
- data/docs/api/Brut/BackEnd.html +1 -1
- data/docs/api/Brut/CLI/App.html +38 -13
- data/docs/api/Brut/CLI/AppRunner.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +2 -2
- data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Create.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Drop.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Migrate.html +9 -3
- data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +11 -11
- data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Seed.html +2 -2
- data/docs/api/Brut/CLI/Apps/DB/Status.html +12 -12
- data/docs/api/Brut/CLI/Apps/DB.html +1 -1
- data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +270 -0
- data/docs/api/Brut/CLI/Apps/DeployBase.html +257 -0
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +585 -0
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +196 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +2 -2
- data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/Audit.html +12 -10
- data/docs/api/Brut/CLI/Apps/Test/E2e.html +8 -8
- data/docs/api/Brut/CLI/Apps/Test/JS.html +9 -9
- data/docs/api/Brut/CLI/Apps/Test/Run.html +18 -18
- data/docs/api/Brut/CLI/Apps/Test.html +1 -1
- data/docs/api/Brut/CLI/Apps.html +2 -2
- data/docs/api/Brut/CLI/Command.html +113 -28
- data/docs/api/Brut/CLI/Error.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
- data/docs/api/Brut/CLI/Executor.html +169 -38
- data/docs/api/Brut/CLI/InvalidOption.html +1 -1
- data/docs/api/Brut/CLI/Options.html +68 -19
- data/docs/api/Brut/CLI/Output.html +1 -1
- data/docs/api/Brut/CLI/SystemExecError.html +1 -1
- data/docs/api/Brut/CLI.html +1 -1
- data/docs/api/Brut/FactoryBot.html +1 -1
- data/docs/api/Brut/Framework/App.html +1 -1
- data/docs/api/Brut/Framework/Config.html +1 -1
- data/docs/api/Brut/Framework/Container.html +110 -29
- data/docs/api/Brut/Framework/Error.html +1 -1
- data/docs/api/Brut/Framework/Errors/AbstractMethod.html +89 -1
- data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
- data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
- data/docs/api/Brut/Framework/Errors.html +31 -8
- data/docs/api/Brut/Framework/FussyTypeEnforcement.html +1 -1
- data/docs/api/Brut/Framework/MCP.html +1 -1
- data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
- data/docs/api/Brut/Framework.html +1 -1
- data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
- data/docs/api/Brut/FrontEnd/Component/Helpers.html +36 -26
- data/docs/api/Brut/FrontEnd/Component.html +7 -7
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +37 -29
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +20 -117
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +25 -23
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +73 -380
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +22 -138
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
- data/docs/api/Brut/FrontEnd/Components.html +23 -2
- data/docs/api/Brut/FrontEnd/Download.html +1 -1
- data/docs/api/Brut/FrontEnd/Flash.html +1 -1
- data/docs/api/Brut/FrontEnd/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +24 -68
- data/docs/api/Brut/FrontEnd/Forms/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +4 -4
- data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +72 -22
- data/docs/api/Brut/FrontEnd/Forms.html +1 -1
- data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
- data/docs/api/Brut/FrontEnd/Handler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
- data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
- data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
- data/docs/api/Brut/FrontEnd/Layout.html +1 -1
- data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +6 -2
- data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
- data/docs/api/Brut/FrontEnd/Page.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages.html +1 -1
- data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing.html +1 -1
- data/docs/api/Brut/FrontEnd/Session.html +1 -1
- data/docs/api/Brut/FrontEnd.html +1 -1
- data/docs/api/Brut/I18n/BaseMethods.html +1 -1
- data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
- data/docs/api/Brut/I18n/ForCLI.html +1 -1
- data/docs/api/Brut/I18n/ForHTML.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
- data/docs/api/Brut/I18n.html +1 -1
- data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry.html +1 -1
- data/docs/api/Brut/Instrumentation.html +1 -1
- data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
- data/docs/api/Brut/SinatraHelpers.html +1 -1
- data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/E2ETestServer.html +20 -20
- data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
- data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/HandlerSupport.html +2 -2
- data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +142 -0
- data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +142 -0
- data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +155 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +55 -25
- data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +149 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +46 -19
- data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +149 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +149 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +165 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +158 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +156 -0
- data/docs/api/Brut/SpecSupport/Matchers.html +2 -2
- data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +24 -24
- data/docs/api/Brut/SpecSupport/RSpecSetup.html +55 -20
- data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
- data/docs/api/Brut/SpecSupport.html +1 -1
- data/docs/api/Brut.html +1 -1
- data/docs/api/Clock.html +1 -1
- data/docs/api/RichString.html +1 -1
- data/docs/api/SemanticLogger/Appender/Async.html +1 -1
- data/docs/api/Sequel/Extensions/BrutInstrumentation.html +5 -1
- data/docs/api/Sequel/Extensions/BrutMigrations.html +36 -28
- data/docs/api/Sequel/Extensions.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang.html +1 -1
- data/docs/api/Sequel/Plugins.html +1 -1
- data/docs/api/Sequel.html +1 -1
- data/docs/api/SpecSupport/Matchers/BeABug.html +143 -0
- data/docs/api/_index.html +92 -1
- data/docs/api/class_list.html +1 -1
- data/docs/api/file.README.html +1 -1
- data/docs/api/index.html +1 -1
- data/docs/api/method_list.html +392 -336
- data/docs/api/top-level-namespace.html +1 -1
- data/docs/assets/{ai.md.tZrjP9im.js → ai.md._6HCDL6d.js} +1 -1
- data/docs/assets/ai.md._6HCDL6d.lean.js +1 -0
- data/docs/assets/{app.D_yaTITQ.js → app.BX81XO4N.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.CoYzciVi.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.B2-ZzyTY.js → VPLocalSearchBox.gABXcTWp.js} +1 -1
- data/docs/assets/chunks/{theme.CfGFVRvE.js → theme.DwUXXAL3.js} +2 -2
- data/docs/assets/{components.md.eCttGlN-.js → components.md.CRUMdRoN.js} +1 -1
- data/docs/assets/{configuration.md.BRriU0cL.js → configuration.md.BGHl8oRC.js} +1 -1
- data/docs/assets/{dev-environment.md.BNc8AYiK.js → dev-environment.md.GZv6xvi9.js} +1 -1
- data/docs/assets/doc-conventions.md.-kN3Xo5C.js +1 -0
- data/docs/assets/{doc-conventions.md.DCfRXXi-.lean.js → doc-conventions.md.-kN3Xo5C.lean.js} +1 -1
- data/docs/assets/{forms.md.CBTYQ_Cz.js → forms.md.B-koVgyw.js} +23 -23
- data/docs/assets/{forms.md.CBTYQ_Cz.lean.js → forms.md.B-koVgyw.lean.js} +1 -1
- data/docs/assets/getting-started.md.Ciz82L0m.js +25 -0
- data/docs/assets/getting-started.md.Ciz82L0m.lean.js +1 -0
- data/docs/assets/{instrumentation.md.CL6ax7nT.js → instrumentation.md.a9Pjps4P.js} +2 -2
- data/docs/assets/{instrumentation.md.CL6ax7nT.lean.js → instrumentation.md.a9Pjps4P.lean.js} +1 -1
- data/docs/assets/layouts.md.cPnh3NId.js +51 -0
- data/docs/assets/layouts.md.cPnh3NId.lean.js +1 -0
- data/docs/assets/lsp.md.Bsu-f6VU.js +1 -0
- data/docs/assets/lsp.md.Bsu-f6VU.lean.js +1 -0
- data/docs/assets/{overview.md.CDalkuxV.js → overview.md.C5wlBcR5.js} +3 -3
- data/docs/assets/recipes_authentication.md.CAsXf7hk.js +1 -0
- data/docs/assets/recipes_authentication.md.CAsXf7hk.lean.js +1 -0
- data/docs/assets.html +4 -4
- data/docs/brut-js/api/AjaxSubmit.html +1 -1
- data/docs/brut-js/api/AjaxSubmit.js.html +1 -1
- data/docs/brut-js/api/Autosubmit.html +1 -1
- data/docs/brut-js/api/Autosubmit.js.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
- data/docs/brut-js/api/BrutCustomElements.html +1 -1
- data/docs/brut-js/api/BufferedLogger.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessage.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessage.js.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
- data/docs/brut-js/api/Form.html +1 -1
- data/docs/brut-js/api/Form.js.html +1 -1
- data/docs/brut-js/api/I18nTranslation.html +1 -1
- data/docs/brut-js/api/I18nTranslation.js.html +1 -1
- data/docs/brut-js/api/LocaleDetection.html +1 -1
- data/docs/brut-js/api/LocaleDetection.js.html +1 -1
- data/docs/brut-js/api/Logger.html +1 -1
- data/docs/brut-js/api/Logger.js.html +1 -1
- data/docs/brut-js/api/Message.html +1 -1
- data/docs/brut-js/api/Message.js.html +1 -1
- data/docs/brut-js/api/PrefixedLogger.html +1 -1
- data/docs/brut-js/api/RichString.html +1 -1
- data/docs/brut-js/api/RichString.js.html +1 -1
- data/docs/brut-js/api/Tabs.html +1 -1
- data/docs/brut-js/api/Tabs.js.html +1 -1
- data/docs/brut-js/api/Tracing.html +1 -1
- data/docs/brut-js/api/Tracing.js.html +1 -1
- data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
- data/docs/brut-js/api/external-Performance.html +1 -1
- data/docs/brut-js/api/external-Promise.html +1 -1
- data/docs/brut-js/api/external-ValidityState.html +1 -1
- data/docs/brut-js/api/external-Window.html +1 -1
- data/docs/brut-js/api/external-fetch.html +1 -1
- data/docs/brut-js/api/global.html +1 -1
- data/docs/brut-js/api/index.html +1 -1
- data/docs/brut-js/api/index.js.html +1 -1
- data/docs/brut-js/api/module-testing.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
- data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
- data/docs/brut-js/api/testing.DOMCreator.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
- data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
- data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
- data/docs/brut-js/api/testing_index.js.html +1 -1
- data/docs/brut-js.html +4 -4
- data/docs/business-logic.html +4 -4
- data/docs/cli.html +4 -4
- data/docs/components.html +6 -6
- data/docs/configuration.html +5 -5
- data/docs/css.html +4 -4
- data/docs/custom-element-tests.html +4 -4
- data/docs/database-access.html +4 -4
- data/docs/database-schema.html +4 -4
- data/docs/deployment.html +4 -4
- data/docs/dev-environment.html +5 -5
- data/docs/doc-conventions.html +5 -5
- data/docs/end-to-end-tests.html +4 -4
- data/docs/flash-and-session.html +4 -4
- data/docs/forms.html +27 -27
- data/docs/getting-started.html +29 -6
- data/docs/handlers.html +4 -4
- data/docs/hashmap.json +1 -1
- data/docs/hooks.html +4 -4
- data/docs/i18n.html +4 -4
- data/docs/index.html +3 -3
- data/docs/instrumentation.html +5 -5
- data/docs/javascript.html +4 -4
- data/docs/jobs.html +4 -4
- data/docs/keyword-injection.html +4 -4
- data/docs/layouts.html +74 -0
- data/docs/lsp.html +24 -0
- data/docs/markdown-examples.html +4 -4
- data/docs/middleware.html +4 -4
- data/docs/not-released.html +4 -4
- data/docs/overview.html +8 -8
- data/docs/pages.html +5 -5
- data/docs/recipes/authentication.html +24 -0
- data/docs/routes.html +4 -4
- data/docs/security.html +4 -4
- data/docs/seed-data.html +4 -4
- data/docs/space-time-continuum.html +4 -4
- data/docs/tutorial.html +4 -4
- data/docs/unit-tests.html +4 -4
- data/lib/brut/cli/app.rb +7 -2
- data/lib/brut/cli/apps/deploy_base.rb +86 -0
- data/lib/brut/cli/apps/heroku_container_based_deploy.rb +194 -0
- data/lib/brut/cli/command.rb +7 -13
- data/lib/brut/cli/executor.rb +31 -5
- data/lib/brut/cli/options.rb +4 -0
- data/lib/brut/cli.rb +4 -3
- data/lib/brut/framework/container.rb +25 -7
- data/lib/brut/framework/errors/abstract_method.rb +7 -0
- data/lib/brut/framework/errors.rb +4 -2
- data/lib/brut/front_end/middlewares/reload_app.rb +2 -0
- data/lib/brut/spec_support/rspec_setup.rb +42 -2
- data/lib/brut/version.rb +1 -1
- data/lib/sequel/extensions/brut_instrumentation.rb +4 -0
- metadata +49 -23
- data/docs/assets/ai.md.tZrjP9im.lean.js +0 -1
- data/docs/assets/chunks/@localSearchIndexroot.BsN5i0Fi.js +0 -1
- data/docs/assets/doc-conventions.md.DCfRXXi-.js +0 -1
- data/docs/assets/getting-started.md.Bz2s1Vjb.js +0 -2
- data/docs/assets/getting-started.md.Bz2s1Vjb.lean.js +0 -1
- /data/docs/assets/{components.md.eCttGlN-.lean.js → components.md.CRUMdRoN.lean.js} +0 -0
- /data/docs/assets/{configuration.md.BRriU0cL.lean.js → configuration.md.BGHl8oRC.lean.js} +0 -0
- /data/docs/assets/{dev-environment.md.BNc8AYiK.lean.js → dev-environment.md.GZv6xvi9.lean.js} +0 -0
- /data/docs/assets/{overview.md.CDalkuxV.lean.js → overview.md.C5wlBcR5.lean.js} +0 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
require "brut/cli"
|
2
|
+
class Brut::CLI::Apps::HerokuContainerBasedDeploy < Brut::CLI::Apps::DeployBase
|
3
|
+
description "Deploy to Heroku using containers"
|
4
|
+
default_command :deploy
|
5
|
+
configure_only!
|
6
|
+
|
7
|
+
class Deploy < Brut::CLI::Command
|
8
|
+
description "Build images, push them to Heroku, and deploy them"
|
9
|
+
|
10
|
+
detailed_description %{
|
11
|
+
Manages a deploy process based on using Heroku's Container Registry. See
|
12
|
+
|
13
|
+
https://devcenter.heroku.com/articles/container-registry-and-runtime
|
14
|
+
|
15
|
+
for details. You are assumed to understand this. This command will make the process somewhat easier.
|
16
|
+
|
17
|
+
This will use deploy/Dockerfile as a template to create one Dockerfile for each process you want to run in Heroku. deploy/heroku_config.rb is where the processes and their commands are configured.
|
18
|
+
|
19
|
+
The release phase is included automatically, based on bin/release.
|
20
|
+
}
|
21
|
+
|
22
|
+
opts.on("--platform=PLATFORM","Override default platform. Can be any Docker platform.")
|
23
|
+
opts.on("--[no-]dry-run", "Print the commands that would be run and don't actually do anything. Implies --skip-checks")
|
24
|
+
opts.on("--[no-]skip-checks", "Skip checks for code having been committed and pushed")
|
25
|
+
opts.on("--[no-]deploy", "After images are pushed, actually deploy them")
|
26
|
+
opts.on("--[no-]push", "After images are created, push them to Heroku's registry. If false, implies --no-deploy")
|
27
|
+
|
28
|
+
def after_bootstrap(app:)
|
29
|
+
@app_id = app.id
|
30
|
+
@organization = app.organization
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute
|
34
|
+
options.set_default(:deploy, true)
|
35
|
+
options.set_default(:push, true)
|
36
|
+
if !options.push?
|
37
|
+
options[:deploy] = false
|
38
|
+
end
|
39
|
+
local_repo_checks = Brut::CLI::Apps::DeployBase::GitChecks.new(
|
40
|
+
out: @out,
|
41
|
+
err: @err,
|
42
|
+
executor: @executor,
|
43
|
+
warn_only: options.skip_checks? || options.dry_run?
|
44
|
+
)
|
45
|
+
if options.dry_run?
|
46
|
+
def system!(*args)
|
47
|
+
out.puts "DRY RUN, NOT EXECUTING '#{args}'"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
version = begin
|
52
|
+
git_guess = %{git rev-parse HEAD}
|
53
|
+
stdout, stderr, status = Open3.capture3(git_guess)
|
54
|
+
if status.success?
|
55
|
+
stdout.strip
|
56
|
+
else
|
57
|
+
raise "Attempt to use git via command '#{git_guess}' to figure out the version failed: #{stdout}#{stderr}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
short_version = version[0..7]
|
61
|
+
|
62
|
+
platform = options.platform || "linux/amd64"
|
63
|
+
heroku_app_name = @app_id
|
64
|
+
|
65
|
+
out.puts "Reading HerokuConfig:"
|
66
|
+
require_relative Brut.container.project_root / "deploy" / "heroku_config"
|
67
|
+
|
68
|
+
additional_images = HerokuConfig.additional_images.map { |name,config|
|
69
|
+
cmd = config.fetch(:cmd)
|
70
|
+
out.puts " - #{name} will run #{cmd} in production"
|
71
|
+
image_name = %{#{@organization}/#{@app_id}:#{short_version}-#{name}}
|
72
|
+
[
|
73
|
+
name,
|
74
|
+
{
|
75
|
+
cmd:,
|
76
|
+
image_name:,
|
77
|
+
dockerfile: "deploy/Dockerfile.#{name}",
|
78
|
+
heroku_image_name: "registry.heroku.com/#{heroku_app_name}/#{name}",
|
79
|
+
}
|
80
|
+
]
|
81
|
+
}.to_h
|
82
|
+
|
83
|
+
images = {
|
84
|
+
"web" => {
|
85
|
+
cmd: "bin/run",
|
86
|
+
image_name: %{#{@organization}/#{@app_id}:#{short_version}-web},
|
87
|
+
dockerfile: "deploy/Dockerfile.web",
|
88
|
+
heroku_image_name: "registry.heroku.com/#{heroku_app_name}/web",
|
89
|
+
},
|
90
|
+
"release" => {
|
91
|
+
cmd: "bin/release",
|
92
|
+
image_name: %{#{@organization}/#{@app_id}:#{short_version}-release},
|
93
|
+
dockerfile: "deploy/Dockerfile.release",
|
94
|
+
heroku_image_name: "registry.heroku.com/#{heroku_app_name}/release",
|
95
|
+
},
|
96
|
+
}.merge(additional_images)
|
97
|
+
|
98
|
+
out.puts " - release will run bin/release in production"
|
99
|
+
|
100
|
+
local_repo_checks.check!
|
101
|
+
require_heroku_login!(options)
|
102
|
+
|
103
|
+
FileUtils.chdir Brut.container.project_root do
|
104
|
+
|
105
|
+
out.puts "Generating Dockerfiles"
|
106
|
+
images.each do |name,metadata|
|
107
|
+
cmd = metadata.fetch(:cmd)
|
108
|
+
dockerfile = metadata.fetch(:dockerfile)
|
109
|
+
|
110
|
+
out.puts "Creating '#{dockerfile}' for '#{name}' that will use command '#{cmd}'"
|
111
|
+
|
112
|
+
File.open(dockerfile,"w") do |file|
|
113
|
+
file.puts "# DO NOT EDIT - THIS IS GENERATED"
|
114
|
+
file.puts "# To make changes, modifiy deploy/Dockerfile and run #{$0}"
|
115
|
+
file.puts File.read("deploy/Dockerfile")
|
116
|
+
file.puts
|
117
|
+
file.puts "# Added by #{$0}"
|
118
|
+
file.puts %{CMD [ "bundle", "exec", "#{cmd}" ]}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
out.puts "Building images"
|
123
|
+
docker_quiet_option = if global_options.log_level != "debug"
|
124
|
+
"--quiet"
|
125
|
+
else
|
126
|
+
""
|
127
|
+
end
|
128
|
+
images.each do |name,metadata|
|
129
|
+
image_name = metadata.fetch(:image_name)
|
130
|
+
dockerfile = metadata.fetch(:dockerfile)
|
131
|
+
|
132
|
+
|
133
|
+
out.puts "Creating docker image with name '#{image_name}' and platform '#{platform}'"
|
134
|
+
command = %{docker build #{docker_quiet_option} --build-arg app_git_sha1=#{version} --file #{Brut.container.project_root}/#{dockerfile} --platform #{platform} --tag #{image_name} .}
|
135
|
+
system!(command)
|
136
|
+
end
|
137
|
+
|
138
|
+
out.puts "Taggging images for Heroku"
|
139
|
+
images.each do |name,metadata|
|
140
|
+
image_name = metadata.fetch(:image_name)
|
141
|
+
heroku_image_name = metadata.fetch(:heroku_image_name)
|
142
|
+
|
143
|
+
out.puts "Tagging '#{image_name}' with '#{heroku_image_name}' for Heroku"
|
144
|
+
command = %{docker tag #{image_name} #{heroku_image_name}}
|
145
|
+
system!(command)
|
146
|
+
end
|
147
|
+
|
148
|
+
if options.push?
|
149
|
+
out.puts "Pushing to Heroku Registry"
|
150
|
+
images.each do |name,metadata|
|
151
|
+
heroku_image_name = metadata.fetch(:heroku_image_name)
|
152
|
+
|
153
|
+
out.puts "Pushing '#{heroku_image_name}'"
|
154
|
+
|
155
|
+
command = %{docker push #{docker_quiet_option} #{heroku_image_name}}
|
156
|
+
system!(command)
|
157
|
+
end
|
158
|
+
else
|
159
|
+
out.puts "Not pushing images"
|
160
|
+
end
|
161
|
+
|
162
|
+
names = images.map(&:first).join(" ")
|
163
|
+
deploy_command = "heroku container:release #{names}"
|
164
|
+
if options.deploy?
|
165
|
+
out.puts "Deploying images to Heroku"
|
166
|
+
system!(deploy_command)
|
167
|
+
else
|
168
|
+
out.puts "Not deploying. To deploy the images just pushed:"
|
169
|
+
out.puts ""
|
170
|
+
out.puts " #{deploy_command}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
private
|
175
|
+
def require_heroku_login!(options)
|
176
|
+
if system("heroku whoami")
|
177
|
+
out.puts "You are logged in to Heroku"
|
178
|
+
else
|
179
|
+
out.puts "You are not logged into Heroku."
|
180
|
+
out.puts "Please run the following:"
|
181
|
+
out.puts ""
|
182
|
+
out.puts "heroku auth:login"
|
183
|
+
out.puts "heroku container:login"
|
184
|
+
out.puts ""
|
185
|
+
out.puts "Then, re-run this"
|
186
|
+
if options.dry_run?
|
187
|
+
out.puts "Dry run - ignoring"
|
188
|
+
return
|
189
|
+
end
|
190
|
+
exit 1
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
data/lib/brut/cli/command.rb
CHANGED
@@ -198,6 +198,13 @@ class Brut::CLI::Command
|
|
198
198
|
def before_execute
|
199
199
|
end
|
200
200
|
|
201
|
+
# Called after all setup has been executed. Brut will have been started/loaded.
|
202
|
+
# This will *not* be called if anything caused execution to be aborted.
|
203
|
+
#
|
204
|
+
# @param [Brut::Framework::App] app Your Brut app.
|
205
|
+
def after_bootstrap(app:)
|
206
|
+
end
|
207
|
+
|
201
208
|
# @!visibility private
|
202
209
|
def set_env_if_needed
|
203
210
|
if self.class.requires_project_env?
|
@@ -219,19 +226,6 @@ class Brut::CLI::Command
|
|
219
226
|
raise ex
|
220
227
|
end
|
221
228
|
|
222
|
-
# @!visibility private
|
223
|
-
def bootstrap!(project_root:, configure_only:)
|
224
|
-
require "bundler"
|
225
|
-
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
|
226
|
-
if configure_only
|
227
|
-
require "#{project_root}/app/pre_boot"
|
228
|
-
Brut::Framework.new(app: ::App.new)
|
229
|
-
else
|
230
|
-
require "#{project_root}/app/boot"
|
231
|
-
end
|
232
|
-
continue_execution
|
233
|
-
end
|
234
|
-
|
235
229
|
private
|
236
230
|
|
237
231
|
# @!visibility public
|
data/lib/brut/cli/executor.rb
CHANGED
@@ -16,14 +16,40 @@ class Brut::CLI::Executor
|
|
16
16
|
@err = err
|
17
17
|
end
|
18
18
|
|
19
|
-
# Execute a command, logging it to the standard output and outputing the
|
20
|
-
#
|
19
|
+
# Execute a command, logging it to the standard output and outputing the
|
20
|
+
# commands output and error to the standard output and error, respectively. If
|
21
|
+
# the command exits nonzero, the exit status is returned.
|
22
|
+
#
|
23
|
+
# Generally, you want to use {#system!} for commands that must succeed
|
24
|
+
# for the caller to continue. Only use this method if you need
|
25
|
+
# to do special error-handling when the underlying command fails.
|
26
|
+
#
|
27
|
+
# @see https://docs.ruby-lang.org/en/3.3/Open3.html#method-c-popen3
|
28
|
+
# @see #system!
|
29
|
+
#
|
30
|
+
# @param [String|Array] args Whatever you would give to `Kernel#system` or `Open3.popen3`.
|
31
|
+
# @return [int] 0 if the command completed normally, otherwise the nonzero exit status. **DO NOT TREAT THIS AS A BOOLEAN VALUE**
|
32
|
+
def system(*args)
|
33
|
+
self.system!(*args)
|
34
|
+
0
|
35
|
+
rescue Brut::CLI::SystemExecError => e
|
36
|
+
e.exit_status
|
37
|
+
end
|
38
|
+
|
39
|
+
# Execute a command, logging it to the standard output and outputing the
|
40
|
+
# commands output and error to the standard output and error, respectively. If
|
41
|
+
# the command exits nonzero, an exception is raised and your CLI app will
|
42
|
+
# also exit nonzero.
|
43
|
+
#
|
44
|
+
# If you need to handle the command exiting nonzero, use {#system}
|
45
|
+
# instead, as it will not raise an exception.
|
21
46
|
#
|
22
47
|
# @see https://docs.ruby-lang.org/en/3.3/Open3.html#method-c-popen3
|
48
|
+
# @see #system
|
23
49
|
#
|
24
50
|
# @param [String|Array] args Whatever you would give to `Kernel#system` or `Open3.popen3`.
|
25
|
-
# @raise Brut::CLI::Error::SystemExecError if the spawed command exits
|
26
|
-
# @return [
|
51
|
+
# @raise Brut::CLI::Error::SystemExecError if the spawed command exits nonzero
|
52
|
+
# @return [int] Always returns 0
|
27
53
|
def system!(*args)
|
28
54
|
@out.puts "Executing #{args}"
|
29
55
|
wait_thread = Open3.popen3(*args) do |_stdin,stdout,stderr,wait_thread|
|
@@ -52,6 +78,6 @@ class Brut::CLI::Executor
|
|
52
78
|
else
|
53
79
|
raise Brut::CLI::SystemExecError.new(args,wait_thread.value.exitstatus)
|
54
80
|
end
|
55
|
-
|
81
|
+
0
|
56
82
|
end
|
57
83
|
end
|
data/lib/brut/cli/options.rb
CHANGED
@@ -12,6 +12,10 @@ class Brut::CLI::Options
|
|
12
12
|
# Access an options value directly.
|
13
13
|
# @param [String] key the key to use. This must be the exact name you used when calling `opts.on` or when creating the `OptionParser` for your app or command. Generally, use the {#method_missing}-provided version instead of this.
|
14
14
|
def [](key) = @parsed_options[key]
|
15
|
+
|
16
|
+
def []=(key,value)
|
17
|
+
@parsed_options[key] = value
|
18
|
+
end
|
15
19
|
# Check if `key` was provided on the command line.
|
16
20
|
# @param [String] key the key to use. This must be the exact name you used when calling `opts.on` or when creating the `OptionParser` for your app or command.
|
17
21
|
def key?(key) = @parsed_options.key?(key)
|
data/lib/brut/cli.rb
CHANGED
@@ -42,9 +42,10 @@ module Brut
|
|
42
42
|
# Holds Brut-provided CLI apps that are set up in your project.
|
43
43
|
module Apps
|
44
44
|
autoload(:DB,"brut/cli/apps/db")
|
45
|
-
autoload(:
|
46
|
-
autoload(:
|
47
|
-
autoload(:
|
45
|
+
autoload(:Test,"brut/cli/apps/test")
|
46
|
+
autoload(:BuildAssets,"brut/cli/apps/build_assets")
|
47
|
+
autoload(:Scaffold,"brut/cli/apps/scaffold")
|
48
|
+
autoload(:DeployBase,"brut/cli/apps/deploy_base")
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
@@ -78,7 +78,7 @@ class Brut::Framework::Container
|
|
78
78
|
self.validate_name!(name:,type:,allow_app_override:)
|
79
79
|
if value == :use_block
|
80
80
|
derive_with = block
|
81
|
-
@container[name] = {
|
81
|
+
@container[name] = { derive_with: derive_with }
|
82
82
|
else
|
83
83
|
if type == :boolean
|
84
84
|
value = !!value
|
@@ -111,9 +111,11 @@ class Brut::Framework::Container
|
|
111
111
|
raise ArgumentError,"#{name} does not allow the app to override it"
|
112
112
|
end
|
113
113
|
if value == :use_block
|
114
|
-
@container[name] =
|
114
|
+
@container[name][:derive_with] = block
|
115
|
+
@container[name].delete(:value)
|
115
116
|
else
|
116
|
-
@container[name] =
|
117
|
+
@container[name][:value] = value
|
118
|
+
@container[name].delete(:derive_with)
|
117
119
|
end
|
118
120
|
end
|
119
121
|
|
@@ -191,16 +193,16 @@ class Brut::Framework::Container
|
|
191
193
|
# TODO: Provide a cleanr impl and better error checking if things go wrong
|
192
194
|
x = @container.fetch(name)
|
193
195
|
|
194
|
-
|
196
|
+
has_value = x.key?(:value)
|
195
197
|
|
196
|
-
if
|
198
|
+
if has_value
|
197
199
|
handle_path_values(name,x)
|
198
|
-
return value
|
200
|
+
return x[:value]
|
199
201
|
end
|
200
202
|
|
201
203
|
deriver = x[:derive_with]
|
202
204
|
if deriver.nil?
|
203
|
-
raise "Something is seriously wrong. '#{name}' was stored in container without a derive_with
|
205
|
+
raise "Something is seriously wrong. '#{name}' was stored in container without a static value, but also without a derive_with key"
|
204
206
|
end
|
205
207
|
|
206
208
|
parameters = deriver.parameters(lambda: true)
|
@@ -218,6 +220,22 @@ class Brut::Framework::Container
|
|
218
220
|
handle_path_values(name,x)
|
219
221
|
x[:value]
|
220
222
|
end
|
223
|
+
|
224
|
+
def reload
|
225
|
+
@container.each do |name, contained_value|
|
226
|
+
if contained_value.key?(:value) && contained_value[:type].to_s == "Class"
|
227
|
+
if contained_value.key?(:derive_with)
|
228
|
+
contained_value.delete(:value)
|
229
|
+
else
|
230
|
+
klass = contained_value[:value]
|
231
|
+
new_klass = klass.name.split(/::/).reduce(Module) { |mod,part|
|
232
|
+
mod.const_get(part)
|
233
|
+
}
|
234
|
+
contained_value[:value] = new_klass
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
221
239
|
private
|
222
240
|
|
223
241
|
def handle_path_values(name,contained_value)
|
@@ -2,4 +2,11 @@
|
|
2
2
|
# which methods a subclass is expected to override and for which no default behavior
|
3
3
|
# makes sense.
|
4
4
|
class Brut::Framework::Errors::AbstractMethod < Brut::Framework::Error
|
5
|
+
def initialize(method_name=nil)
|
6
|
+
if method_name
|
7
|
+
super("The method `#{method_name}` must be implemented")
|
8
|
+
else
|
9
|
+
super("An abstract method must be implemented")
|
10
|
+
end
|
11
|
+
end
|
5
12
|
end
|
@@ -27,9 +27,11 @@ module Brut
|
|
27
27
|
# a method that a subclass must implement, but for which there is no useful default
|
28
28
|
# implementation.
|
29
29
|
#
|
30
|
+
# @param [String|Symbol] method_name name of the method that must be implemented. If omitted, the value is guessed from `caller_locations`
|
30
31
|
# @raise [Brut::Framework::Errors::AbstractMethod]
|
31
|
-
def abstract_method!
|
32
|
-
|
32
|
+
def abstract_method!(method_name=nil)
|
33
|
+
method_name ||= caller_locations(1,1)[0].label
|
34
|
+
raise Brut::Framework::Errors::AbstractMethod.new(method_name)
|
33
35
|
end
|
34
36
|
end
|
35
37
|
# Base class for errors thrown by Brut classes. Generally, Brut will not create its own version
|
@@ -28,6 +28,8 @@ class Brut::FrontEnd::Middlewares::ReloadApp < Brut::FrontEnd::Middleware
|
|
28
28
|
span.add_event("Routing reloaded")
|
29
29
|
Brut.container.asset_path_resolver.reload
|
30
30
|
span.add_event("Asset Path Resolver reloaded")
|
31
|
+
Brut.container.reload
|
32
|
+
span.add_event("Brut.container reloaded")
|
31
33
|
::I18n.reload!
|
32
34
|
span.add_event("I18n reloaded")
|
33
35
|
rescue => ex
|
@@ -43,8 +43,16 @@ class Brut::SpecSupport::RSpecSetup
|
|
43
43
|
# Create the setup with the given RSpec configuration.
|
44
44
|
#
|
45
45
|
# @param [RSpec::Core::Configuration] rspec_config yielded from `RSpec.configure`
|
46
|
-
|
47
|
-
|
46
|
+
# @param [boolean] monkey_patch_summary_notification if true (the default),
|
47
|
+
# RSpec's Notifications::SumaryNotification will be monkey-patched to show
|
48
|
+
# `bin/test` in the summary instead of `./rspec`, as that is how you would
|
49
|
+
# re-run a test. But, it's still monkey-patching.
|
50
|
+
def initialize(rspec_config:,
|
51
|
+
monkey_patch_summary_notification: true)
|
52
|
+
|
53
|
+
@config = rspec_config
|
54
|
+
@monkey_patch_summary_notification = monkey_patch_summary_notification
|
55
|
+
|
48
56
|
SemanticLogger.default_level = ENV.fetch("LOGGER_LEVEL_FOR_TESTS","warn")
|
49
57
|
end
|
50
58
|
|
@@ -155,6 +163,9 @@ class Brut::SpecSupport::RSpecSetup
|
|
155
163
|
@config.after(:suite) do
|
156
164
|
Brut::SpecSupport::E2ETestServer.instance.stop
|
157
165
|
end
|
166
|
+
if @monkey_patch_summary_notification
|
167
|
+
monkey_patch_summary_notification!
|
168
|
+
end
|
158
169
|
end
|
159
170
|
|
160
171
|
class OptionalSidekiqSupport
|
@@ -181,4 +192,33 @@ class Brut::SpecSupport::RSpecSetup
|
|
181
192
|
end
|
182
193
|
end
|
183
194
|
|
195
|
+
private
|
196
|
+
|
197
|
+
def monkey_patch_summary_notification!
|
198
|
+
require "rspec/core/notifications"
|
199
|
+
klass = RSpec::Core::Notifications::SummaryNotification
|
200
|
+
if !klass.instance_variable_get("@_brut_has_monkeypatched")
|
201
|
+
klass.class_eval do
|
202
|
+
# Slightly reformatted, but the only line that's different
|
203
|
+
# is the one that said to use './rspec'. Now it says 'bin/test run'
|
204
|
+
def colorized_rerun_commands(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
|
205
|
+
"\nFailed examples:\n\n" +
|
206
|
+
failed_examples.map do |example|
|
207
|
+
rerun_argument = rerun_argument_for(example)
|
208
|
+
colorizer.wrap(
|
209
|
+
"bin/test run #{rerun_argument}", # <--- this is the only difference
|
210
|
+
RSpec.configuration.failure_color
|
211
|
+
) +
|
212
|
+
" " +
|
213
|
+
colorizer.wrap(
|
214
|
+
"# #{example.full_description}",
|
215
|
+
RSpec.configuration.detail_color
|
216
|
+
)
|
217
|
+
end.join("\n")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
klass.instance_variable_set("@_brut_has_monkeypatched",true)
|
221
|
+
end
|
222
|
+
end
|
184
223
|
end
|
224
|
+
|
data/lib/brut/version.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Sequel
|
2
2
|
module Extensions
|
3
3
|
# Instruments all SQL executions.
|
4
|
+
#
|
5
|
+
# *NOTE* this will include the actual SQL query text in the
|
6
|
+
# span, so any literal values in the query will be in the observability
|
7
|
+
# platforms.
|
4
8
|
module BrutInstrumentation
|
5
9
|
# @!visibility private
|
6
10
|
def log_connection_yield(sql,conn,args=nil)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Bryant Copeland
|
@@ -614,6 +614,7 @@ files:
|
|
614
614
|
- brutrb.com/javascript.md
|
615
615
|
- brutrb.com/jobs.md
|
616
616
|
- brutrb.com/keyword-injection.md
|
617
|
+
- brutrb.com/layouts.md
|
617
618
|
- brutrb.com/lsp.md
|
618
619
|
- brutrb.com/markdown-examples.md
|
619
620
|
- brutrb.com/middleware.md
|
@@ -662,6 +663,10 @@ files:
|
|
662
663
|
- docs/api/Brut/CLI/Apps/DB/Rebuild.html
|
663
664
|
- docs/api/Brut/CLI/Apps/DB/Seed.html
|
664
665
|
- docs/api/Brut/CLI/Apps/DB/Status.html
|
666
|
+
- docs/api/Brut/CLI/Apps/DeployBase.html
|
667
|
+
- docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html
|
668
|
+
- docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html
|
669
|
+
- docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html
|
665
670
|
- docs/api/Brut/CLI/Apps/Scaffold.html
|
666
671
|
- docs/api/Brut/CLI/Apps/Scaffold/Action.html
|
667
672
|
- docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html
|
@@ -803,8 +808,17 @@ files:
|
|
803
808
|
- docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html
|
804
809
|
- docs/api/Brut/SpecSupport/HandlerSupport.html
|
805
810
|
- docs/api/Brut/SpecSupport/Matchers.html
|
811
|
+
- docs/api/Brut/SpecSupport/Matchers/BeABug.html
|
812
|
+
- docs/api/Brut/SpecSupport/Matchers/BePageFor.html
|
813
|
+
- docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html
|
806
814
|
- docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html
|
815
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html
|
807
816
|
- docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html
|
817
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html
|
818
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html
|
819
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html
|
820
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html
|
821
|
+
- docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html
|
808
822
|
- docs/api/Brut/SpecSupport/RSpecSetup.html
|
809
823
|
- docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html
|
810
824
|
- docs/api/Brut/SpecSupport/SessionSupport.html
|
@@ -823,6 +837,7 @@ files:
|
|
823
837
|
- docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html
|
824
838
|
- docs/api/Sequel/Plugins/FindBang.html
|
825
839
|
- docs/api/Sequel/Plugins/FindBang/ClassMethods.html
|
840
|
+
- docs/api/SpecSupport/Matchers/BeABug.html
|
826
841
|
- docs/api/_index.html
|
827
842
|
- docs/api/class_list.html
|
828
843
|
- docs/api/css/common.css
|
@@ -838,25 +853,25 @@ files:
|
|
838
853
|
- docs/api/method_list.html
|
839
854
|
- docs/api/top-level-namespace.html
|
840
855
|
- docs/assets.html
|
841
|
-
- docs/assets/ai.md.
|
842
|
-
- docs/assets/ai.md.
|
843
|
-
- docs/assets/app.
|
856
|
+
- docs/assets/ai.md._6HCDL6d.js
|
857
|
+
- docs/assets/ai.md._6HCDL6d.lean.js
|
858
|
+
- docs/assets/app.BX81XO4N.js
|
844
859
|
- docs/assets/assets.md.D3wunzLx.js
|
845
860
|
- docs/assets/assets.md.D3wunzLx.lean.js
|
846
861
|
- docs/assets/brut-js.md.o2DAO2s2.js
|
847
862
|
- docs/assets/brut-js.md.o2DAO2s2.lean.js
|
848
863
|
- docs/assets/business-logic.md.BY4hGy0m.js
|
849
864
|
- docs/assets/business-logic.md.BY4hGy0m.lean.js
|
850
|
-
- docs/assets/chunks/@localSearchIndexroot.
|
851
|
-
- docs/assets/chunks/VPLocalSearchBox.
|
865
|
+
- docs/assets/chunks/@localSearchIndexroot.CoYzciVi.js
|
866
|
+
- docs/assets/chunks/VPLocalSearchBox.gABXcTWp.js
|
852
867
|
- docs/assets/chunks/framework.1L-BeKqY.js
|
853
|
-
- docs/assets/chunks/theme.
|
868
|
+
- docs/assets/chunks/theme.DwUXXAL3.js
|
854
869
|
- docs/assets/cli.md.RmeA2b0i.js
|
855
870
|
- docs/assets/cli.md.RmeA2b0i.lean.js
|
856
|
-
- docs/assets/components.md.
|
857
|
-
- docs/assets/components.md.
|
858
|
-
- docs/assets/configuration.md.
|
859
|
-
- docs/assets/configuration.md.
|
871
|
+
- docs/assets/components.md.CRUMdRoN.js
|
872
|
+
- docs/assets/components.md.CRUMdRoN.lean.js
|
873
|
+
- docs/assets/configuration.md.BGHl8oRC.js
|
874
|
+
- docs/assets/configuration.md.BGHl8oRC.lean.js
|
860
875
|
- docs/assets/css.md.DJgj2clw.js
|
861
876
|
- docs/assets/css.md.DJgj2clw.lean.js
|
862
877
|
- docs/assets/custom-element-tests.md.BrYJQEl3.js
|
@@ -869,18 +884,18 @@ files:
|
|
869
884
|
- docs/assets/deployment.md.Dbka4OTr.lean.js
|
870
885
|
- docs/assets/dev-env-overview.Gj7NWM8-.png
|
871
886
|
- docs/assets/dev-env-protocol.DysDAtnz.png
|
872
|
-
- docs/assets/dev-environment.md.
|
873
|
-
- docs/assets/dev-environment.md.
|
874
|
-
- docs/assets/doc-conventions.md.
|
875
|
-
- docs/assets/doc-conventions.md.
|
887
|
+
- docs/assets/dev-environment.md.GZv6xvi9.js
|
888
|
+
- docs/assets/dev-environment.md.GZv6xvi9.lean.js
|
889
|
+
- docs/assets/doc-conventions.md.-kN3Xo5C.js
|
890
|
+
- docs/assets/doc-conventions.md.-kN3Xo5C.lean.js
|
876
891
|
- docs/assets/end-to-end-tests.md.yfQHC0b5.js
|
877
892
|
- docs/assets/end-to-end-tests.md.yfQHC0b5.lean.js
|
878
893
|
- docs/assets/flash-and-session.md.BXY8RvT0.js
|
879
894
|
- docs/assets/flash-and-session.md.BXY8RvT0.lean.js
|
880
|
-
- docs/assets/forms.md.
|
881
|
-
- docs/assets/forms.md.
|
882
|
-
- docs/assets/getting-started.md.
|
883
|
-
- docs/assets/getting-started.md.
|
895
|
+
- docs/assets/forms.md.B-koVgyw.js
|
896
|
+
- docs/assets/forms.md.B-koVgyw.lean.js
|
897
|
+
- docs/assets/getting-started.md.Ciz82L0m.js
|
898
|
+
- docs/assets/getting-started.md.Ciz82L0m.lean.js
|
884
899
|
- docs/assets/handlers.md.089DVD3v.js
|
885
900
|
- docs/assets/handlers.md.089DVD3v.lean.js
|
886
901
|
- docs/assets/hooks.md.C4-moMny.js
|
@@ -889,14 +904,18 @@ files:
|
|
889
904
|
- docs/assets/i18n.md.Do9i1qWl.lean.js
|
890
905
|
- docs/assets/index.md.B28EwVpq.js
|
891
906
|
- docs/assets/index.md.B28EwVpq.lean.js
|
892
|
-
- docs/assets/instrumentation.md.
|
893
|
-
- docs/assets/instrumentation.md.
|
907
|
+
- docs/assets/instrumentation.md.a9Pjps4P.js
|
908
|
+
- docs/assets/instrumentation.md.a9Pjps4P.lean.js
|
894
909
|
- docs/assets/javascript.md.GWbhRS51.js
|
895
910
|
- docs/assets/javascript.md.GWbhRS51.lean.js
|
896
911
|
- docs/assets/jobs.md.S-2amAYp.js
|
897
912
|
- docs/assets/jobs.md.S-2amAYp.lean.js
|
898
913
|
- docs/assets/keyword-injection.md.Dt2tKREs.js
|
899
914
|
- docs/assets/keyword-injection.md.Dt2tKREs.lean.js
|
915
|
+
- docs/assets/layouts.md.cPnh3NId.js
|
916
|
+
- docs/assets/layouts.md.cPnh3NId.lean.js
|
917
|
+
- docs/assets/lsp.md.Bsu-f6VU.js
|
918
|
+
- docs/assets/lsp.md.Bsu-f6VU.lean.js
|
900
919
|
- docs/assets/markdown-examples.md.CCFEQO44.js
|
901
920
|
- docs/assets/markdown-examples.md.CCFEQO44.lean.js
|
902
921
|
- docs/assets/middleware.md.Czz_UlJN.js
|
@@ -904,10 +923,12 @@ files:
|
|
904
923
|
- docs/assets/not-released.md.BBy28McC.js
|
905
924
|
- docs/assets/not-released.md.BBy28McC.lean.js
|
906
925
|
- docs/assets/overview.Da81cB9R.png
|
907
|
-
- docs/assets/overview.md.
|
908
|
-
- docs/assets/overview.md.
|
926
|
+
- docs/assets/overview.md.C5wlBcR5.js
|
927
|
+
- docs/assets/overview.md.C5wlBcR5.lean.js
|
909
928
|
- docs/assets/pages.md.BE3kfOc5.js
|
910
929
|
- docs/assets/pages.md.BE3kfOc5.lean.js
|
930
|
+
- docs/assets/recipes_authentication.md.CAsXf7hk.js
|
931
|
+
- docs/assets/recipes_authentication.md.CAsXf7hk.lean.js
|
911
932
|
- docs/assets/routes.md.BMM7peut.js
|
912
933
|
- docs/assets/routes.md.BMM7peut.lean.js
|
913
934
|
- docs/assets/security.md.C668yXCi.js
|
@@ -1040,11 +1061,14 @@ files:
|
|
1040
1061
|
- docs/javascript.html
|
1041
1062
|
- docs/jobs.html
|
1042
1063
|
- docs/keyword-injection.html
|
1064
|
+
- docs/layouts.html
|
1065
|
+
- docs/lsp.html
|
1043
1066
|
- docs/markdown-examples.html
|
1044
1067
|
- docs/middleware.html
|
1045
1068
|
- docs/not-released.html
|
1046
1069
|
- docs/overview.html
|
1047
1070
|
- docs/pages.html
|
1071
|
+
- docs/recipes/authentication.html
|
1048
1072
|
- docs/routes.html
|
1049
1073
|
- docs/security.html
|
1050
1074
|
- docs/seed-data.html
|
@@ -1075,6 +1099,8 @@ files:
|
|
1075
1099
|
- lib/brut/cli/app_runner.rb
|
1076
1100
|
- lib/brut/cli/apps/build_assets.rb
|
1077
1101
|
- lib/brut/cli/apps/db.rb
|
1102
|
+
- lib/brut/cli/apps/deploy_base.rb
|
1103
|
+
- lib/brut/cli/apps/heroku_container_based_deploy.rb
|
1078
1104
|
- lib/brut/cli/apps/scaffold.rb
|
1079
1105
|
- lib/brut/cli/apps/test.rb
|
1080
1106
|
- lib/brut/cli/command.rb
|
@@ -1 +0,0 @@
|
|
1
|
-
import{_ as t,c as o,o as a,ag as s}from"./chunks/framework.1L-BeKqY.js";const b=JSON.parse('{"title":"AI Declaration and Notes","description":"","frontmatter":{},"headers":[],"relativePath":"ai.md","filePath":"ai.md"}'),r={name:"ai.md"};function n(i,e,l,d,h,u){return a(),o("div",null,e[0]||(e[0]=[s("",26)]))}const p=t(r,[["render",n]]);export{b as __pageData,p as default};
|