From 4f7f0e96b0245fce7fb47beb60205f16661125a8 Mon Sep 17 00:00:00 2001 From: Faye Date: Thu, 21 May 2026 12:04:44 +0200 Subject: [PATCH 1/2] Add start, end, start-ts and end-ts flags to log environment command --- cmd/kosli/logEnvironment.go | 50 +++++++++++++++++++++++++++++--- cmd/kosli/logEnvironment_test.go | 35 ++++++++++++++++++++++ cmd/kosli/root.go | 4 +++ 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/cmd/kosli/logEnvironment.go b/cmd/kosli/logEnvironment.go index 3d3422dc9..afbc73ce0 100644 --- a/cmd/kosli/logEnvironment.go +++ b/cmd/kosli/logEnvironment.go @@ -18,14 +18,16 @@ const logEnvironmentLongDesc = logEnvironmentShortDesc + ` The results are paginated and ordered from latest to oldest. By default, the page limit is 15 events per page. -You can optionally specify an INTERVAL between two snapshot expressions with [expression]..[expression]. +You can optionally specify an INTERVAL between two snapshot expressions with [expression]..[expression]. Expressions can be: -* ~N N'th behind the latest snapshot -* N snapshot number N -* NOW the latest snapshot +* ~N N'th behind the latest snapshot +* N snapshot number N +* NOW the latest snapshot Either expression can be omitted to default to NOW. + +You can also filter events by range using --start/--end (snapshot index or time expression such as "NOW" or "1hour") or --start-ts/--end-ts (Unix timestamps). ` const logEnvironmentExample = ` @@ -59,6 +61,26 @@ kosli log environment yourEnvironmentName \ --repo yourOrg/yourRepo2 \ --api-token yourAPIToken \ --org yourOrgName + +# list events starting from snapshot 5: +kosli log environment yourEnvironmentName \ + --start 5 \ + --api-token yourAPIToken \ + --org yourOrgName + +# list events between two time expressions: +kosli log environment yourEnvironmentName \ + --start 1hour \ + --end NOW \ + --api-token yourAPIToken \ + --org yourOrgName + +# list events between two Unix timestamps: +kosli log environment yourEnvironmentName \ + --start-ts 1700000000 \ + --end-ts 1700086400 \ + --api-token yourAPIToken \ + --org yourOrgName ` type logEnvironmentOptions struct { @@ -66,6 +88,10 @@ type logEnvironmentOptions struct { reverse bool interval string repos []string + start string + end string + startTS float64 + endTS float64 } func newLogEnvironmentCmd(out io.Writer) *cobra.Command { @@ -92,6 +118,10 @@ func newLogEnvironmentCmd(out io.Writer) *cobra.Command { cmd.Flags().StringVarP(&o.interval, "interval", "i", "", intervalFlag) cmd.Flags().StringSliceVar(&o.repos, "repo", []string{}, repoNameFlag) + cmd.Flags().StringVar(&o.start, "start", "", eventsStartFlag) + cmd.Flags().StringVar(&o.end, "end", "", eventsEndFlag) + cmd.Flags().Float64Var(&o.startTS, "start-ts", 0, eventsStartTSFlag) + cmd.Flags().Float64Var(&o.endTS, "end-ts", 0, eventsEndTSFlag) addListFlags(cmd, &o.listOptions) cmd.Flags().BoolVar(&o.reverse, "reverse", false, reverseFlag) @@ -126,6 +156,18 @@ func (o *logEnvironmentOptions) getEnvironmentEvents(out io.Writer, envName, int q.Add("repo_name", repo) } } + if o.start != "" { + q.Set("start", o.start) + } + if o.end != "" { + q.Set("end", o.end) + } + if o.startTS != 0 { + q.Set("start_ts", strconv.FormatFloat(o.startTS, 'f', -1, 64)) + } + if o.endTS != 0 { + q.Set("end_ts", strconv.FormatFloat(o.endTS, 'f', -1, 64)) + } u.RawQuery = q.Encode() reqParams := &requests.RequestParams{ diff --git a/cmd/kosli/logEnvironment_test.go b/cmd/kosli/logEnvironment_test.go index f8b181cd6..5eb22d9c4 100644 --- a/cmd/kosli/logEnvironment_test.go +++ b/cmd/kosli/logEnvironment_test.go @@ -152,6 +152,41 @@ func (suite *LogEnvironmentCommandTestSuite) TestLogEnvironmentCmd() { reportToEnv: true, }, }, + { + name: "listing events with --start as snapshot index works", + cmd: fmt.Sprintf(`log env %s --start 1 %s`, suite.eventsEnvName, suite.defaultKosliArguments), + additionalConfig: listSnapshotsTestConfig{ + reportToEnv: true, + }, + }, + { + name: "listing events with --end as snapshot index works", + cmd: fmt.Sprintf(`log env %s --end 2 %s`, suite.eventsEnvName, suite.defaultKosliArguments), + additionalConfig: listSnapshotsTestConfig{ + reportToEnv: true, + }, + }, + { + name: "listing events with --start and --end as time expressions works", + cmd: fmt.Sprintf(`log env %s --start 1hour --end NOW %s`, suite.eventsEnvName, suite.defaultKosliArguments), + additionalConfig: listSnapshotsTestConfig{ + reportToEnv: true, + }, + }, + { + name: "listing events with --start-ts and --end-ts works", + cmd: fmt.Sprintf(`log env %s --start-ts 1700000000 --end-ts 1700086400 %s`, suite.eventsEnvName, suite.defaultKosliArguments), + additionalConfig: listSnapshotsTestConfig{ + reportToEnv: true, + }, + }, + { + name: "listing events with --start-ts as float works", + cmd: fmt.Sprintf(`log env %s --start-ts 1700000000.5 %s`, suite.eventsEnvName, suite.defaultKosliArguments), + additionalConfig: listSnapshotsTestConfig{ + reportToEnv: true, + }, + }, } for _, t := range tests { diff --git a/cmd/kosli/root.go b/cmd/kosli/root.go index ff05e699b..c8469fece 100644 --- a/cmd/kosli/root.go +++ b/cmd/kosli/root.go @@ -273,6 +273,10 @@ The ^.kosli_ignore^ will be treated as part of the artifact like any other file, getAttestationFlowNameFlag = "[conditional] The name of the Kosli flow for the attestation. Required if ATTESTATION-NAME provided. Cannot be used together with --attestation-id." attestationIDFlag = "[conditional] The unique identifier of the attestation to retrieve. Cannot be used together with ATTESTATION-NAME." repoNameFlag = "[optional] The name of a git repo as it is registered in Kosli. e.g kosli-dev/cli" + eventsStartFlag = "[optional] The start of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." + eventsEndFlag = "[optional] The end of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." + eventsStartTSFlag = "[optional] The start of the events range as a Unix timestamp (integer or float)." + eventsEndTSFlag = "[optional] The end of the events range as a Unix timestamp (integer or float)." attestationRepoNameFlag = "[conditional] The name of the repository (e.g. owner/repo-name). All three of --repo-id, --repo-url and --repository must be set to record repository information (defaulted in some CIs: https://docs.kosli.com/integrations/ci_cd )." ) From 9429c44d5952d415a37fb22664888f988999fb71 Mon Sep 17 00:00:00 2001 From: Faye Date: Thu, 21 May 2026 14:07:43 +0200 Subject: [PATCH 2/2] Add unit to start-ts and end-ts flags --- cmd/kosli/root.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/kosli/root.go b/cmd/kosli/root.go index c8469fece..81012b22a 100644 --- a/cmd/kosli/root.go +++ b/cmd/kosli/root.go @@ -273,10 +273,10 @@ The ^.kosli_ignore^ will be treated as part of the artifact like any other file, getAttestationFlowNameFlag = "[conditional] The name of the Kosli flow for the attestation. Required if ATTESTATION-NAME provided. Cannot be used together with --attestation-id." attestationIDFlag = "[conditional] The unique identifier of the attestation to retrieve. Cannot be used together with ATTESTATION-NAME." repoNameFlag = "[optional] The name of a git repo as it is registered in Kosli. e.g kosli-dev/cli" - eventsStartFlag = "[optional] The start of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." - eventsEndFlag = "[optional] The end of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." - eventsStartTSFlag = "[optional] The start of the events range as a Unix timestamp (integer or float)." - eventsEndTSFlag = "[optional] The end of the events range as a Unix timestamp (integer or float)." + eventsStartFlag = "[optional] The start of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." + eventsEndFlag = "[optional] The end of the events range. Can be a snapshot index (integer) or a time expression (e.g. NOW, 1hour)." + eventsStartTSFlag = "[optional] The start of the events range as a Unix timestamp in seconds (integer or float)." + eventsEndTSFlag = "[optional] The end of the events range as a Unix timestamp in seconds (integer or float)." attestationRepoNameFlag = "[conditional] The name of the repository (e.g. owner/repo-name). All three of --repo-id, --repo-url and --repository must be set to record repository information (defaulted in some CIs: https://docs.kosli.com/integrations/ci_cd )." )