chore: fieldalignment across code base to reduce memory usage

This commit is contained in:
jamesread 2026-07-28 22:26:51 +01:00
parent e6a232f21b
commit a1f03e7d33
16 changed files with 162 additions and 181 deletions

View File

@ -9,10 +9,10 @@ import (
func Test_hasGroupsMatch(t *testing.T) {
tests := []struct {
name string
aclMatchUsergroups []string
usergroupLine string
matches bool
sep string
aclMatchUsergroups []string
matches bool
}{
{
name: "No groups match",

View File

@ -63,9 +63,9 @@ func (api *oliveTinAPI) copyOfStreamingClients() []*streamingClient {
type streamingClient struct {
channel chan *apiv1.EventStreamResponse
AuthenticatedUser *authpublic.AuthenticatedUser
heartbeatStopOnce sync.Once
heartbeatStop chan struct{}
heartbeatDone chan struct{}
heartbeatStopOnce sync.Once
}
func (c *streamingClient) stopHeartbeat() {

View File

@ -25,9 +25,9 @@ type DashboardRenderRequest struct {
AuthenticatedUser *authpublic.AuthenticatedUser
cfg *config.Config
ex *executor.Executor
activeBindingStates map[string]bindingActiveState
EntityType string
EntityKey string
activeBindingStates map[string]bindingActiveState
}
func activeBindingID(entry *executor.InternalLogEntry) string {

View File

@ -226,9 +226,9 @@ func validateConsistency(t *testing.T, client apiv1connect.OliveTinApiServiceCli
func TestEvaluateEnabledExpression(t *testing.T) {
tests := []struct {
entity *entities.Entity
name string
expression string
entity *entities.Entity
expectedResult bool
}{
{

View File

@ -10,15 +10,12 @@ import (
// User represents a person.
type AuthenticatedUser struct {
EffectivePolicy *config.ConfigurationPolicy
Username string
UsergroupLine string
Provider string
SID string
Acls []string
EffectivePolicy *config.ConfigurationPolicy
}
func (u *AuthenticatedUser) IsGuest() bool {

View File

@ -10,8 +10,8 @@ func Test_parseUsergroupLine(t *testing.T) {
tests := []struct {
name string
usergroupLine string
expectedGroups []string
sep string
expectedGroups []string
}{
{
name: "Default separator (space)",

View File

@ -22,9 +22,9 @@ import (
type OAuth2Handler struct {
cfg *config.Config
mu sync.RWMutex
registeredStates map[string]*oauth2State
registeredProviders map[string]*oauth2.Config
mu sync.RWMutex
}
func NewOAuth2Handler(cfg *config.Config) *OAuth2Handler {
@ -58,11 +58,11 @@ func NewOAuth2Handler(cfg *config.Config) *OAuth2Handler {
}
type oauth2State struct {
createdAt time.Time
providerConfig *oauth2.Config
providerName string
Username string
Usergroup string
createdAt time.Time
}
const (

View File

@ -13,34 +13,33 @@ const JustificationRequiredNoTemplate = " "
// Action represents the core functionality of OliveTin - commands that show up
// as buttons in the UI.
type Action struct {
ID string `koanf:"id"`
Title string `koanf:"title"`
Icon string `koanf:"icon"`
SaveLogs SaveLogsConfig `koanf:"saveLogs"`
Shell string `koanf:"shell"`
Exec []string `koanf:"exec"`
ShellAfterCompleted string `koanf:"shellAfterCompleted"`
Timeout int `koanf:"timeout"`
Acls []string `koanf:"acls"`
Entity string `koanf:"entity"`
Hidden bool `koanf:"hidden"`
ExecOnStartup bool `koanf:"execOnStartup"`
ExecOnCron []string `koanf:"execOnCron"`
ExecOnFileCreatedInDir []string `koanf:"execOnFileCreatedInDir"`
ExecOnFileChangedInDir []string `koanf:"execOnFileChangedInDir"`
Icon string `koanf:"icon"`
ExecOnCalendarFile string `koanf:"execOnCalendarFile"`
SourceFile string `koanf:"-"`
ShellAfterCompleted string `koanf:"shellAfterCompleted"`
Justification string `koanf:"justification"`
EnabledExpression string `koanf:"enabledExpression"`
Entity string `koanf:"entity"`
Title string `koanf:"title"`
PopupOnStart string `koanf:"popupOnStart"`
OnClick string `koanf:"onclick"`
ID string `koanf:"id"`
MaxRate []RateSpec `koanf:"maxRate"`
Acls []string `koanf:"acls"`
ExecOnWebhook []WebhookConfig `koanf:"execOnWebhook"`
Triggers []string `koanf:"triggers"`
MaxConcurrent int `koanf:"maxConcurrent"`
MaxRate []RateSpec `koanf:"maxRate"`
Exec []string `koanf:"exec"`
ExecOnFileCreatedInDir []string `koanf:"execOnFileCreatedInDir"`
Arguments []ActionArgument `koanf:"arguments"`
OnClick string `koanf:"onclick"`
PopupOnStart string `koanf:"popupOnStart"`
SaveLogs SaveLogsConfig `koanf:"saveLogs"`
EnabledExpression string `koanf:"enabledExpression"`
ExecOnCron []string `koanf:"execOnCron"`
Groups []string `koanf:"groups"`
Justification string `koanf:"justification"`
// SourceFile is set by OliveTin when loading config (not user YAML).
SourceFile string `koanf:"-"`
ExecOnFileChangedInDir []string `koanf:"execOnFileChangedInDir"`
Timeout int `koanf:"timeout"`
MaxConcurrent int `koanf:"maxConcurrent"`
Hidden bool `koanf:"hidden"`
ExecOnStartup bool `koanf:"execOnStartup"`
}
func (action *Action) RequiresJustification() bool {
@ -61,23 +60,23 @@ func (action *Action) JustificationTemplateText() string {
// ActionGroup defines shared limits and metadata for a set of actions.
type ActionGroup struct {
Icon string `koanf:"icon"`
MaxConcurrent int `koanf:"maxConcurrent"`
QueueSize int `koanf:"queueSize"`
Icon string `koanf:"icon"`
}
// ActionArgument objects appear on Actions.
type ActionArgument struct {
Suggestions map[string]string `koanf:"suggestions"`
Name string `koanf:"name"`
Title string `koanf:"title"`
Description string `koanf:"description"`
Type string `koanf:"type"`
Default string `koanf:"default"`
Choices []ActionArgumentChoice `koanf:"choices"`
Entity string `koanf:"entity"`
RejectNull bool `koanf:"rejectNull"`
Suggestions map[string]string `koanf:"suggestions"`
SuggestionsBrowserKey string `koanf:"suggestionsBrowserKey"`
Choices []ActionArgumentChoice `koanf:"choices"`
RejectNull bool `koanf:"rejectNull"`
}
// ActionArgumentChoice represents a predefined choice for an argument.
@ -88,8 +87,8 @@ type ActionArgumentChoice struct {
// RateSpec allows you to set a max frequency for an action.
type RateSpec struct {
Limit int `koanf:"limit"`
Duration string `koanf:"duration"`
Limit int `koanf:"limit"`
}
// WebhookConfig defines configuration for generic webhook triggers.
@ -111,9 +110,8 @@ type EntityFile struct {
File string `koanf:"file"`
Name string `koanf:"name"`
Icon string `koanf:"icon"`
Properties []EntityProperty `koanf:"properties"`
// SourceFile is set by OliveTin when loading config (not user YAML).
SourceFile string `koanf:"-"`
Properties []EntityProperty `koanf:"properties"`
}
// EntityProperty defines a column shown when listing entity instances in the UI.
@ -133,11 +131,11 @@ type PermissionsList struct {
// AccessControlList defines what permissions apply to a user or user group.
type AccessControlList struct {
Name string `koanf:"name"`
AddToEveryAction bool `koanf:"addToEveryAction"`
MatchUsergroups []string `koanf:"matchUsergroups"`
MatchUsernames []string `koanf:"matchUsernames"`
Permissions PermissionsList `koanf:"permissions"`
Policy ConfigurationPolicy `koanf:"policy"`
AddToEveryAction bool `koanf:"addToEveryAction"`
}
// ConfigurationPolicy defines global settings which are overridden with an ACL.
@ -154,88 +152,87 @@ type PrometheusConfig struct {
// SecurityConfig allows users to fine tune the security related HTTP headers and cookie options.
type SecurityConfig struct {
HeaderContentSecurityPolicy bool `koanf:"headerContentSecurityPolicy"`
ContentSecurityPolicy string `koanf:"contentSecurityPolicy"`
XFrameOptions string `koanf:"xFrameOptions"`
HeaderContentSecurityPolicy bool `koanf:"headerContentSecurityPolicy"`
HeaderXContentTypeOptions bool `koanf:"headerXContentTypeOptions"`
HeaderXFrameOptions bool `koanf:"headerXFrameOptions"`
XFrameOptions string `koanf:"xFrameOptions"`
ForceSecureCookies bool `koanf:"forceSecureCookies"`
}
// Config is the global config used through the whole app.
type Config struct {
UseSingleHTTPFrontend bool `koanf:"useSingleHTTPFrontend"`
ThemeName string `koanf:"themeName"`
ThemeCacheDisabled bool `koanf:"themeCacheDisabled"`
ListenAddressSingleHTTPFrontend string `koanf:"listenAddressSingleHTTPFrontend"`
ListenAddressWebUI string `koanf:"listenAddressWebUI"`
ActionGroups map[string]*ActionGroup `koanf:"actionGroups"`
AuthOAuth2Providers map[string]*OAuth2Provider `koanf:"authOAuth2Providers"`
SaveLogs SaveLogsConfig `koanf:"saveLogs"`
DefaultIconForBack string `koanf:"defaultIconForBack"`
AuthOAuth2RedirectURL string `koanf:"authOAuth2RedirectUrl"`
ListenAddressRestActions string `koanf:"listenAddressRestActions"`
ListenAddressPrometheus string `koanf:"listenAddressPrometheus"`
ExternalRestAddress string `koanf:"externalRestAddress"`
LogLevel string `koanf:"logLevel"`
LogDebugOptions LogDebugOptions `koanf:"logDebugOptions"`
LogHistoryPageSize int64 `koanf:"logHistoryPageSize"`
ActionGroups map[string]*ActionGroup `koanf:"actionGroups"`
Actions []*Action `koanf:"actions"`
Entities []*EntityFile `koanf:"entities"`
Dashboards []*DashboardComponent `koanf:"dashboards"`
CheckForUpdates bool `koanf:"checkForUpdates"`
ThemeName string `koanf:"themeName"`
ServiceLogs ServiceLogsConfig `koanf:"serviceLogs"`
ListenAddressSingleHTTPFrontend string `koanf:"listenAddressSingleHTTPFrontend"`
AuthJwtHmacSecret string `koanf:"authJwtHmacSecret"`
AuthJwtCertsURL string `koanf:"authJwtCertsUrl"`
DefaultIconForActions string `koanf:"defaultIconForActions"`
Include string `koanf:"include"`
PageTitle string `koanf:"pageTitle"`
ShowFooter bool `koanf:"showFooter"`
ShowNavigation bool `koanf:"showNavigation"`
ShowNewVersions bool `koanf:"showNewVersions"`
ShowNavigateOnStartIcons bool `koanf:"showNavigateOnStartIcons"`
EnableCustomJs bool `koanf:"enableCustomJs"`
BannerCSS string `koanf:"bannerCss"`
BannerMessage string `koanf:"bannerMessage"`
DefaultPopupOnStart string `koanf:"defaultPopupOnStart"`
ServiceHostMode string `koanf:"serviceHostMode"`
DefaultOnClick string `koanf:"defaultOnClick"`
AuthJwtCookieName string `koanf:"authJwtCookieName"`
AuthJwtHeader string `koanf:"authJwtHeader"`
AuthJwtAud string `koanf:"authJwtAud"`
AuthJwtDomain string `koanf:"authJwtDomain"`
AuthJwtCertsURL string `koanf:"authJwtCertsUrl"`
AuthJwtHmacSecret string `koanf:"authJwtHmacSecret"` // mutually exclusive with pub key config fields
ListenAddressWebUI string `koanf:"listenAddressWebUI"`
SectionNavigationStyle string `koanf:"sectionNavigationStyle"`
DefaultIconForDirectories string `koanf:"defaultIconForDirectories"`
AuthJwtClaimUsername string `koanf:"authJwtClaimUsername"`
AuthJwtClaimUserGroup string `koanf:"authJwtClaimUserGroup"`
AuthJwtPubKeyPath string `koanf:"authJwtPubKeyPath"` // will read pub key from file on disk
AuthJwtPubKeyPath string `koanf:"authJwtPubKeyPath"`
AuthHttpHeaderUsername string `koanf:"authHttpHeaderUsername"`
AuthHttpHeaderUserGroup string `koanf:"authHttpHeaderUserGroup"`
AuthHttpHeaderUserGroupSep string `koanf:"authHttpHeaderUserGroupSep"`
AuthLocalUsers AuthLocalUsersConfig `koanf:"authLocalUsers"`
WebUIDir string `koanf:"webUIDir"`
AuthLoginUrl string `koanf:"authLoginUrl"`
AuthRequireGuestsToLogin bool `koanf:"authRequireGuestsToLogin"`
AuthOAuth2RedirectURL string `koanf:"authOAuth2RedirectUrl"`
AuthOAuth2Providers map[string]*OAuth2Provider `koanf:"authOAuth2Providers"`
AuthJwtDomain string `koanf:"authJwtDomain"`
Security SecurityConfig `koanf:"security"`
Actions []*Action `koanf:"actions"`
AccessControlLists []*AccessControlList `koanf:"accessControlLists"`
StyleMods []string `koanf:"styleMods"`
AdditionalNavigationLinks []*NavigationLink `koanf:"additionalNavigationLinks"`
Entities []*EntityFile `koanf:"entities"`
Dashboards []*DashboardComponent `koanf:"dashboards"`
sourceFiles []string
AuthLocalUsers AuthLocalUsersConfig `koanf:"authLocalUsers"`
LogHistoryPageSize int64 `koanf:"logHistoryPageSize"`
LogDebugOptions LogDebugOptions `koanf:"logDebugOptions"`
DefaultPermissions PermissionsList `koanf:"defaultPermissions"`
DefaultPolicy ConfigurationPolicy `koanf:"defaultPolicy"`
AccessControlLists []*AccessControlList `koanf:"accessControlLists"`
WebUIDir string `koanf:"webUIDir"`
CronSupportForSeconds bool `koanf:"cronSupportForSeconds"`
SectionNavigationStyle string `koanf:"sectionNavigationStyle"`
DefaultOnClick string `koanf:"defaultOnClick"`
DefaultPopupOnStart string `koanf:"defaultPopupOnStart"`
InsecureAllowDumpOAuth2UserData bool `koanf:"insecureAllowDumpOAuth2UserData"`
InsecureAllowDumpVars bool `koanf:"insecureAllowDumpVars"`
InsecureAllowDumpServerDiagnostics bool `koanf:"insecureAllowDumpServerDiagnostics"`
InsecureAllowDumpActionMap bool `koanf:"insecureAllowDumpActionMap"`
InsecureAllowDumpJwtClaims bool `koanf:"insecureAllowDumpJwtClaims"`
Prometheus PrometheusConfig `koanf:"prometheus"`
Security SecurityConfig `koanf:"security"`
SaveLogs SaveLogsConfig `koanf:"saveLogs"`
ServiceLogs ServiceLogsConfig `koanf:"serviceLogs"`
DefaultIconForActions string `koanf:"defaultIconForActions"`
DefaultIconForDirectories string `koanf:"defaultIconForDirectories"`
DefaultIconForBack string `koanf:"defaultIconForBack"`
AdditionalNavigationLinks []*NavigationLink `koanf:"additionalNavigationLinks"`
ServiceHostMode string `koanf:"serviceHostMode"`
StyleMods []string `koanf:"styleMods"`
BannerMessage string `koanf:"bannerMessage"`
BannerCSS string `koanf:"bannerCss"`
Include string `koanf:"include"`
sourceFiles []string
CheckForUpdates bool `koanf:"checkForUpdates"`
InsecureAllowDumpJwtClaims bool `koanf:"insecureAllowDumpJwtClaims"`
InsecureAllowDumpActionMap bool `koanf:"insecureAllowDumpActionMap"`
InsecureAllowDumpServerDiagnostics bool `koanf:"insecureAllowDumpServerDiagnostics"`
InsecureAllowDumpVars bool `koanf:"insecureAllowDumpVars"`
InsecureAllowDumpOAuth2UserData bool `koanf:"insecureAllowDumpOAuth2UserData"`
CronSupportForSeconds bool `koanf:"cronSupportForSeconds"`
AuthRequireGuestsToLogin bool `koanf:"authRequireGuestsToLogin"`
EnableCustomJs bool `koanf:"enableCustomJs"`
ShowNavigateOnStartIcons bool `koanf:"showNavigateOnStartIcons"`
ShowNewVersions bool `koanf:"showNewVersions"`
ShowNavigation bool `koanf:"showNavigation"`
ShowFooter bool `koanf:"showFooter"`
UseSingleHTTPFrontend bool `koanf:"useSingleHTTPFrontend"`
ThemeCacheDisabled bool `koanf:"themeCacheDisabled"`
}
type AuthLocalUsersConfig struct {
Enabled bool `koanf:"enabled"`
Users []*LocalUser `koanf:"users"`
Enabled bool `koanf:"enabled"`
}
type LocalUser struct {
@ -246,21 +243,21 @@ type LocalUser struct {
}
type OAuth2Provider struct {
Name string `koanf:"name"`
Title string `koanf:"title"`
AuthUrl string `koanf:"authUrl"`
UserGroupField string `koanf:"userGroupField"`
ClientID string `koanf:"clientId"`
ClientSecret string `koanf:"clientSecret"`
Icon string `koanf:"icon"`
Scopes []string `koanf:"scopes"`
AuthUrl string `koanf:"authUrl"`
TokenUrl string `koanf:"tokenUrl"`
WhoamiUrl string `koanf:"whoamiUrl"`
UsernameField string `koanf:"usernameField"`
UserGroupField string `koanf:"userGroupField"`
InsecureSkipVerify bool `koanf:"insecureSkipVerify"`
CallbackTimeout int `koanf:"callbackTimeout"`
CertBundlePath string `koanf:"certBundlePath"`
AddToUsergroup string `koanf:"addToUsergroup"`
Title string `koanf:"title"`
WhoamiUrl string `koanf:"whoamiUrl"`
Name string `koanf:"name"`
UsernameField string `koanf:"usernameField"`
TokenUrl string `koanf:"tokenUrl"`
CertBundlePath string `koanf:"certBundlePath"`
Scopes []string `koanf:"scopes"`
CallbackTimeout int `koanf:"callbackTimeout"`
InsecureSkipVerify bool `koanf:"insecureSkipVerify"`
}
type NavigationLink struct {

View File

@ -981,12 +981,12 @@ func TestTypecheckActionArgumentHtmlWithoutName(t *testing.T) {
func TestParseCommandForReplacements(t *testing.T) {
tests := []struct {
values map[string]string
name string
shellCommand string
values map[string]string
expectedOutput string
expectError bool
errorContains string
expectError bool
}{
{
name: "Simple replacement",
@ -1052,10 +1052,10 @@ func TestParseCommandForReplacements(t *testing.T) {
func TestArgumentChoicesValidation(t *testing.T) {
tests := []struct {
name string
req *ExecutionRequest
expectError bool
name string
description string
expectError bool
}{
{
name: "Valid choice",

View File

@ -40,53 +40,46 @@ func isValidTrackingID(id string) bool {
}
type ActionBinding struct {
ID string
Action *config.Action
Entity *entities.Entity
ConfigOrder int
ID string
OnDashboards []DashboardNavigationTarget
ConfigOrder int
}
// Executor represents a helper class for executing commands. It's main method
// is ExecRequest
type Executor struct {
logs map[string]*InternalLogEntry
logsTrackingIdsByDate []string
LogsByBindingId map[string][]*InternalLogEntry
logmutex sync.RWMutex
MapActionBindings map[string]*ActionBinding
MapActionBindingsLock sync.RWMutex
Cfg *config.Config
logsTrackingIdsByDate []string
listeners []listener
listenersMu sync.RWMutex
chainOfCommand []executorStepFunc
groupQueue []*queuedExecution
logmutex sync.RWMutex
MapActionBindingsLock sync.RWMutex
listenersMu sync.RWMutex
groupQueueMu sync.Mutex
}
// ExecutionRequest is a request to execute an action. It's passed to an
// Executor. They're created from the api.
type ExecutionRequest struct {
Binding *ActionBinding
Arguments map[string]string
TrackingID string
Tags []string
Binding *ActionBinding
Cfg *config.Config
AuthenticatedUser *authpublic.AuthenticatedUser
TriggerDepth int
Justification string
executor *Executor
logEntry *InternalLogEntry
finalParsedCommand string
TrackingID string
Justification string
Tags []string
execArgs []string
TriggerDepth int
useDirectExec bool
executor *Executor
skipRequestRegistration bool
}
@ -104,12 +97,12 @@ func (req *ExecutionRequest) mutateLogEntry(mutator func(*InternalLogEntry)) {
// LogEntrySnapshot is a copy of selected log entry fields for race-safe reads.
type LogEntrySnapshot struct {
Output string
ExitCode int32
Queued bool
Blocked bool
ExecutionStarted bool
ExecutionFinished bool
ExitCode int32
Output string
}
// SnapshotLog returns a copy of selected log entry fields under read lock.
@ -136,34 +129,28 @@ func (e *Executor) SnapshotLog(trackingID string) (LogEntrySnapshot, bool) {
// state of execution (even if the command is not executed). It's designed to be
// easily serializable.
type InternalLogEntry struct {
Binding *ActionBinding
DatetimeStarted time.Time
DatetimeFinished time.Time
Output string
TimedOut bool
Blocked bool
Queued bool
QueuedForGroup string
ExitCode int32
Tags []string
ExecutionStarted bool
ExecutionFinished bool
ExecutionTrackingID string
Binding *ActionBinding
Process *os.Process
Username string
Index int64
EntityPrefix string
ActionConfigTitle string // This is the title of the action as defined in the config, not the final parsed title.
/*
The following 3 properties are obviously on Action normally, but it's useful
that logs are lightweight (so we don't need to have an action associated to
logs, etc. Therefore, we duplicate those values here.
*/
ActionTitle string
ActionIcon string
Justification string
Arguments map[string]string
ExecutionTrackingID string
Justification string
QueuedForGroup string
ActionIcon string
ActionTitle string
ActionConfigTitle string
Output string
Username string
EntityPrefix string
Tags []string
Index int64
ExitCode int32
Blocked bool
ExecutionFinished bool
ExecutionStarted bool
Queued bool
TimedOut bool
}
// .Binding can be nil, so we need to handle that.
@ -1098,8 +1085,8 @@ func appendErrorToStderr(req *ExecutionRequest, err error) {
type OutputStreamer struct {
Req *ExecutionRequest
mu sync.Mutex
output bytes.Buffer
mu sync.Mutex
}
func (ost *OutputStreamer) Write(o []byte) (n int, err error) {

View File

@ -39,12 +39,12 @@ type WatchMeta struct {
}
type watchContext struct {
filename string
filedir string
callback func(filename string)
interestedEvent fsnotify.Op
event *fsnotify.Event
meta WatchMeta
filename string
filedir string
interestedEvent fsnotify.Op
}
func WatchDirectoryCreate(fullpath string, callback func(filename string), meta WatchMeta) {

View File

@ -16,7 +16,6 @@ type RuntimeInfo struct {
OS string
OSReleasePrettyName string
Arch string
InContainer bool
LastBrowserUserAgent string
User string
Uid string
@ -25,6 +24,7 @@ type RuntimeInfo struct {
AvailableVersion string
WebuiDirectory string
ThemesDirectory string
InContainer bool
}
var Runtime = &RuntimeInfo{

View File

@ -13,8 +13,6 @@ var (
)
type serverDiagnosticsConfig struct {
CountOfActions int
CountOfDashboards int
LogLevel string
ListenAddressSingleHTTPFrontend string
ListenAddressWebUI string
@ -23,6 +21,8 @@ type serverDiagnosticsConfig struct {
TimeNow string
ConfigDirectory string
WebuiDirectory string
CountOfActions int
CountOfDashboards int
}
func configToServerDiagnostics(cfg *config.Config) *serverDiagnosticsConfig {

View File

@ -5,12 +5,12 @@ type Record struct {
Status string
Action string
User string
Output string
Tags []string
ExitCode int32
Blocked bool
TimedOut bool
Running bool
ExitCode int32
Output string
}
// StatusLabel matches the status text shown in the web UI.

View File

@ -13,9 +13,9 @@ import (
)
type versionMapType struct {
ApiVersion int
Latest string
History map[string]string
Latest string
ApiVersion int
}
// StartUpdateChecker will start a job that runs periodically, checking

View File

@ -42,20 +42,20 @@ type runSummary struct {
}
type jsonlRecord struct {
Run int `json:"run"`
Timestamp string `json:"timestamp"`
FailureDetails []testFailure `json:"failureDetails"`
Run int `json:"run"`
ExitCode int `json:"exitCode"`
DurationMs int64 `json:"durationMs"`
Passes int `json:"passes"`
Failures int `json:"failures"`
Skipped int `json:"skipped"`
FailureDetails []testFailure `json:"failureDetails"`
}
type testRunState struct {
summary runSummary
failures []testFailure
failureOutput map[string]*strings.Builder
failures []testFailure
summary runSummary
}
func initLog() {