gitlab-labkit 5.6.0 → 5.6.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb00f476a5fed0be71839727d4fb5d8230f773831c8c8cca40ff8090c76cb2c5
4
- data.tar.gz: c382bf0eed9e55b283eb90c3956a00c8dbf73ad5819fb22e8dd6a1be931fd9ff
3
+ metadata.gz: a1ef319c707c40ea0cca46358bbacdf18d1068b8f2b778ebc1a1486c33cea1ef
4
+ data.tar.gz: 5cbead469ab098d29afb9dcf2dd97576976a703db93eda7ea337a54bc94fcde9
5
5
  SHA512:
6
- metadata.gz: 5932210330aa7c8c4413de43f8ae710508658846c89f1b7b74e1d8d36af564b61034988a6248bf9795d6343602d4b1579d6a9aff48795cda1163c545377932b9
7
- data.tar.gz: ddc501d350806e384f122f152f6ceb7066487bc4f41078341f1ae13373631adf52a1f5cd427a69e879482cf3dc1dff75bbfe7cd57dd1237094c595e615acc591
6
+ metadata.gz: 1488c581703cab14db63d485aa2ef3159d8a0cd8449cc34b4aeeb522d97ad2207edb57096f388240cff213ef44aaa925a8219a2464b3ab4054a81b0e8569129a
7
+ data.tar.gz: 4c65d98b9b29084a3c5bdc7e0d9dc166a4708f203840a08180421172f21c0356005641557e46dc14f48fb277570f4bdae041d61072c454dbdfa252e4e8baf5fd
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env bash
2
+ # PostToolUse hook: validate a just-edited file against this repo's pre-commit rules.
3
+ #
4
+ # Runs `pre-commit run --files <file>` on the file that Edit/Write/MultiEdit
5
+ # touched. On failure it prints the output to stderr and exits 2, which feeds the
6
+ # result back to Claude so it can fix the issue. A clean run exits 0 silently.
7
+ set -euo pipefail
8
+
9
+ # no-commit-to-branch guards the branch, not file content, and would fire
10
+ # spuriously (e.g. on jj's detached HEAD). It is irrelevant to file validation.
11
+ export SKIP="no-commit-to-branch"
12
+
13
+ # Run through `mise exec` so mise-managed tools that the hooks rely on
14
+ # (pre-commit, jsonnet-tool, shfmt, ...) are on PATH, matching a normal
15
+ # interactive shell.
16
+ if ! command -v mise >/dev/null 2>&1; then
17
+ echo "pre-commit validation hook requires mise to run." >&2
18
+ exit 1
19
+ fi
20
+
21
+ run() { mise exec -- "$@"; }
22
+
23
+ repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
24
+
25
+ input="$(cat)"
26
+ file="$(printf '%s' "$input" | mise exec jq@1.8 -- jq -r '.tool_input.file_path // empty')"
27
+ [[ -z $file ]] && exit 0
28
+
29
+ # Only validate files that live inside this repository.
30
+ case "$file" in
31
+ "$repo_root"/*) ;;
32
+ *) exit 0 ;;
33
+ esac
34
+
35
+ if ! output="$(cd "$repo_root" && run pre-commit run --files "$file" 2>&1)"; then
36
+ {
37
+ echo "pre-commit reported issues on ${file#"$repo_root"/}:"
38
+ echo
39
+ echo "$output"
40
+ echo
41
+ echo "Re-read the file (hooks such as trailing-whitespace, shfmt, and"
42
+ echo "generate may have rewritten it) and fix any remaining problems."
43
+ } >&2
44
+ exit 2
45
+ fi
46
+
47
+ exit 0
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write|MultiEdit",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/precommit-validate.sh\""
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
data/.copier-answers.yml CHANGED
@@ -3,7 +3,7 @@
3
3
  # See the project for instructions on how to update the project
4
4
  #
5
5
  # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
6
- _commit: v1.60.0
6
+ _commit: v1.85.0
7
7
  _src_path: https://gitlab.com/gitlab-com/gl-infra/common-template-copier.git
8
8
  ee_licensed: false
9
9
  gitlab_namespace: gitlab-org/ruby/gems
@@ -17,5 +17,6 @@ release_platform: false
17
17
  ruby: true
18
18
  rubygem: true
19
19
  rust: false
20
+ scaffold_target: repo
20
21
  terraform: false
21
22
  truncated_tags: true
data/.gitignore CHANGED
@@ -2,5 +2,4 @@ Gemfile.lock
2
2
  *.gem
3
3
  node_modules
4
4
  .bundle
5
- /.env.sh
6
5
  .idea/
@@ -7,22 +7,22 @@
7
7
  image: registry.gitlab.com/gitlab-com/gl-infra/common-ci-tasks-images/duo-workflow-sandbox:latest
8
8
 
9
9
  setup_script:
10
- # Keep mise's data + cache inside the project dir so the `cache:` block below
11
- # can capture them (caching only reliably covers paths under the project dir).
12
- - export MISE_DATA_DIR="${CI_PROJECT_DIR}/.cache/mise/data"
13
- - export MISE_CACHE_DIR="${CI_PROJECT_DIR}/.cache/mise/cache"
14
- - mise trust --yes
15
- - mise install --yes
10
+ # duo-workflow-setup (baked into the image) exports some variables as
11
+ # `export KEY=VALUE` lines on stdout, which we `eval` into the flow's shell.
12
+ - eval "$(/usr/local/bin/duo-workflow-setup)"
16
13
 
17
14
  cache:
18
- # Re-use installed tools as long as the version pins are unchanged.
15
+ # Re-use installed tools and primed pre-commit hooks as long as the version
16
+ # pins / hook config are unchanged.
19
17
  key:
20
18
  files:
21
19
  - .tool-versions
22
20
  - .mise.toml
21
+ - .pre-commit-config.yaml
23
22
  paths:
24
23
  - .cache/mise/data
25
24
  - .cache/mise/cache
25
+ - .cache/pre-commit
26
26
 
27
27
  network_policy:
28
28
  # Allow the Sandbox Runtime's recommended allowlist (GitLab, package
data/.mise.toml CHANGED
@@ -7,6 +7,9 @@ legacy_version_file = false
7
7
  # OpenSSL and sidesteps it. This becomes mise's default in 2026.8.0.
8
8
  ruby.compile = false
9
9
 
10
+ # Disable sending anonymous download statistics to mise-versions.jdx.dev.
11
+ use_versions_host_track = false
12
+
10
13
  [tools]
11
14
  # Please continue to use `.tool-versions` to specify tool versions, rather than adding them directly here.
12
15
 
@@ -0,0 +1,101 @@
1
+ import type { Plugin, Hooks } from "@opencode-ai/plugin";
2
+ import { existsSync } from "node:fs";
3
+ import { isAbsolute, join, resolve } from "node:path";
4
+
5
+ /**
6
+ * precommit-validate plugin
7
+ *
8
+ * OpenCode equivalent of the Claude Code PostToolUse hook defined in
9
+ * `.claude/hooks/precommit-validate.sh` (wired up by `.claude/settings.json`).
10
+ *
11
+ * After the agent edits or writes a file, this runs that *same* shell script to
12
+ * validate the file against the repo's pre-commit rules. When pre-commit reports
13
+ * problems, the findings are appended to the tool result so the agent sees them
14
+ * on its next turn and can fix the file. A clean run is silent.
15
+ *
16
+ * The script's exit codes mirror Claude Code's hook contract, so we honour the
17
+ * same distinction here:
18
+ * - 0 = clean or no-op (silent)
19
+ * - 2 = pre-commit reported issues; feed the report back to the model
20
+ * - any other non-zero = non-blocking error (e.g. mise missing); log it for
21
+ * the user but do not nag the model, since it can't fix its environment.
22
+ *
23
+ * The script is reused verbatim: it reads Claude Code's PostToolUse payload on
24
+ * stdin (`{ "tool_input": { "file_path": "..." } }`), so we synthesize that same
25
+ * shape here from OpenCode's tool arguments.
26
+ *
27
+ * Auto-loaded from `.opencode/plugins/`.
28
+ */
29
+
30
+ // OpenCode file-mutating tools, analogous to Claude Code's `Edit|Write|MultiEdit`
31
+ // matcher. Current OpenCode may use `apply_patch` for file edits.
32
+ const FILE_TOOLS = new Set(["apply_patch", "edit", "write"]);
33
+
34
+ const HOOK_SCRIPT = ".claude/hooks/precommit-validate.sh";
35
+
36
+ export const PrecommitValidatePlugin: Plugin = async ({ $, client, directory, worktree }) => {
37
+ const root = worktree || directory;
38
+ const script = join(root, HOOK_SCRIPT);
39
+
40
+ const hooks: Hooks = {
41
+ "tool.execute.after": async (input, output) => {
42
+ if (!FILE_TOOLS.has(input.tool)) return;
43
+ // Inert when the shared script is absent (e.g. loaded in another repo).
44
+ if (!existsSync(script)) return;
45
+
46
+ const filePaths = new Set<string>();
47
+ const filePath: string | undefined = input.args?.filePath;
48
+ if (filePath) filePaths.add(filePath);
49
+
50
+ for (const file of output.metadata?.files ?? []) {
51
+ if (typeof file.filePath === "string") filePaths.add(file.filePath);
52
+ }
53
+
54
+ if (filePaths.size === 0) return;
55
+
56
+ const reports: string[] = [];
57
+
58
+ for (const filePath of filePaths) {
59
+ const absolute = isAbsolute(filePath) ? filePath : resolve(root, filePath);
60
+
61
+ // Same JSON shape Claude Code's PostToolUse hook delivers on stdin. The
62
+ // script itself decides whether the file lives inside the repo.
63
+ const payload = JSON.stringify({ tool_input: { file_path: absolute } });
64
+
65
+ const result = await $`printf '%s' ${payload} | ${script}`
66
+ .cwd(root)
67
+ .nothrow()
68
+ .quiet();
69
+
70
+ if (result.exitCode === 0) continue; // clean / no-op
71
+
72
+ const report =
73
+ result.stderr.toString().trim() || result.stdout.toString().trim();
74
+
75
+ if (result.exitCode === 2) {
76
+ // Blocking: pre-commit reported issues. Surface them to the model by
77
+ // appending to the tool output, the OpenCode equivalent of feeding the
78
+ // hook's stderr back to Claude Code on exit 2.
79
+ if (report) reports.push(report);
80
+ continue;
81
+ }
82
+
83
+ // Non-blocking error (e.g. exit 1 = mise not on PATH). Not something the
84
+ // model can act on, so log it for the user instead of polluting the turn.
85
+ await client.app.log({
86
+ body: {
87
+ service: "precommit-validate",
88
+ level: "warn",
89
+ message: report || `pre-commit validation hook exited ${result.exitCode}`,
90
+ },
91
+ });
92
+ }
93
+
94
+ if (reports.length > 0) {
95
+ output.output += `\n\n<pre-commit-validation>\n${reports.join("\n\n")}\n</pre-commit-validation>`;
96
+ }
97
+ },
98
+ };
99
+
100
+ return hooks;
101
+ };
@@ -15,7 +15,7 @@ repos:
15
15
  - id: check-json
16
16
  - id: detect-private-key
17
17
  - id: mixed-line-ending
18
- args: ["--fix=lf"]
18
+ args: [--fix=lf]
19
19
  - id: no-commit-to-branch
20
20
  args: [--branch, main]
21
21
  - id: pretty-format-json
@@ -36,3 +36,4 @@ repos:
36
36
  - id: gitleaks # Detect hardcoded secrets using Gitleaks
37
37
  - id: editorconfig # Validate text files against .editorconfig
38
38
  - id: yamllint # Validate YAML files using yamllint
39
+ - id: ensure-claude-md
data/.rubocop_todo.yml CHANGED
@@ -151,12 +151,6 @@ Lint/SymbolConversion:
151
151
  - 'spec/labkit/logging/json_logger_spec.rb'
152
152
  - 'spec/support/tracing/shared_examples.rb'
153
153
 
154
- # Offense count: 1
155
- # Configuration parameters: Methods.
156
- Lint/UnexpectedBlockArity:
157
- Exclude:
158
- - 'tools/update-changelog.rb'
159
-
160
154
  # Offense count: 41
161
155
  # This cop supports safe autocorrection (--autocorrect).
162
156
  # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
@@ -196,13 +190,6 @@ Naming/RescuedExceptionsVariableName:
196
190
  Exclude:
197
191
  - 'lib/labkit/logging/grpc/server_interceptor.rb'
198
192
 
199
- # Offense count: 1
200
- # This cop supports safe autocorrection (--autocorrect).
201
- # Configuration parameters: EnabledForFlattenWithoutParams.
202
- Performance/FlatMap:
203
- Exclude:
204
- - 'tools/update-changelog.rb'
205
-
206
193
  # Offense count: 1
207
194
  Performance/MethodObjectAsBlock:
208
195
  Exclude:
@@ -402,7 +389,7 @@ Style/FileNull:
402
389
  - 'spec/labkit/middleware/sidekiq/user_experience_sli/server_spec.rb'
403
390
  - 'spec/spec_helper.rb'
404
391
 
405
- # Offense count: 8
392
+ # Offense count: 7
406
393
  # This cop supports unsafe autocorrection (--autocorrect-all).
407
394
  # Configuration parameters: EnforcedStyle.
408
395
  # SupportedStyles: always, always_true, never
@@ -415,7 +402,6 @@ Style/FrozenStringLiteralComment:
415
402
  - 'spec/labkit/tracing/rails/active_support/cache_read_instrumenter_spec.rb'
416
403
  - 'spec/labkit/tracing/rails/active_support/cache_write_instrumenter_spec.rb'
417
404
  - 'spec/support/grpc_service/test_services_pb.rb'
418
- - 'tools/update-changelog.rb'
419
405
 
420
406
  # Offense count: 2
421
407
  # This cop supports unsafe autocorrection (--autocorrect-all).
@@ -539,7 +525,7 @@ Style/StringConcatenation:
539
525
  - 'lib/labkit/tracing/jaeger_factory.rb'
540
526
  - 'lib/labkit/tracing/redis/redis_interceptor_helper.rb'
541
527
 
542
- # Offense count: 6
528
+ # Offense count: 4
543
529
  # This cop supports safe autocorrection (--autocorrect).
544
530
  # Configuration parameters: EnforcedStyle.
545
531
  # SupportedStyles: single_quotes, double_quotes
@@ -549,7 +535,6 @@ Style/StringLiteralsInInterpolation:
549
535
  - 'lib/labkit/tracing/grpc/server_interceptor.rb'
550
536
  - 'lib/labkit/tracing/jaeger_factory.rb'
551
537
  - 'spec/labkit/logging/json_logger_spec.rb'
552
- - 'tools/update-changelog.rb'
553
538
 
554
539
  # Offense count: 10
555
540
  # This cop supports safe autocorrection (--autocorrect).
data/AGENTS.md CHANGED
@@ -1,3 +1,4 @@
1
+ <<<<<<< before updating
1
2
  # AGENTS.md
2
3
 
3
4
  Instructions for AI agents and automated tooling working in this repository.
@@ -134,3 +135,39 @@ When a change does not fit one layer clearly, say so in the MR instead of pickin
134
135
  Mention the sync agent on the review thread to have it draft the scenario MR; if it cannot, open a labkit-spec issue and link it from the thread.
135
136
  - Never edit Lua scripts, key construction, header names, metric names, or log field names to fix a Ruby-only bug.
136
137
  If a fix seems to need that, it is a contract change.
138
+ =======
139
+ # Agent guidelines
140
+
141
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/).
142
+ Commit messages drive automated [semantic releases](https://semantic-release.gitbook.io/)
143
+ (see `.releaserc.json`), so use `feat:`, `fix:`, etc. prefixes to ensure the
144
+ correct version bump and changelog entry.
145
+
146
+ ## AI-authored GitLab comments
147
+
148
+ Wrap the full body of any comment, note, or reply you post to GitLab (issues,
149
+ merge requests, epics — via `glab`/`glab api`) in `<:robot:>` / `</:robot:>`
150
+ tags (GitLab emoji shortcode, renders as 🤖), so readers can tell at a glance
151
+ that it's AI-generated:
152
+
153
+ ```
154
+ <:robot:>
155
+
156
+ ...full comment body...
157
+
158
+ </:robot:>
159
+ ```
160
+
161
+ This applies to newly posted comments. It does not apply to code, commit
162
+ messages, or MR/issue descriptions unless asked.
163
+
164
+ <!--
165
+ ####################################################################
166
+ # 🌊✨ PLEASE ADD PROJECT SPECIFIC RULES BELOW THIS LINE ✨🌊 #
167
+ # The section above is managed by the common-template-copier #
168
+ # template and is updated automatically on `copier update`. #
169
+ # Add your project-specific instructions below this line so #
170
+ # they are preserved when the template is updated. #
171
+ ####################################################################
172
+ -->
173
+ >>>>>>> after updating
data/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
data/Gemfile CHANGED
@@ -3,3 +3,8 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
+
7
+ # Exports RSpec results to the DX Observer when GLCI_OBSERVER_AUTH_TOKEN is set.
8
+ # Exporter source: https://gitlab.com/gitlab-org/quality/analytics/test-metrics-exporters
9
+ # Owned by: @gitlab-org/quality/analytics (group::development analytics)
10
+ gem 'gitlab-rspec-metrics-exporter', '~> 0.2', groups: [:development, :test]
data/README.md CHANGED
@@ -80,27 +80,14 @@ pass.
80
80
 
81
81
  Please also review the [development section of the LabKit (go) README](https://gitlab.com/gitlab-org/labkit#developing-labkit) for details of the LabKit architectural philosophy.
82
82
 
83
- To work on some of the scripts we use for releasing a new version,
84
- make sure to add a new `.env.sh`.
85
-
86
- ```console
87
- cp .env.example.sh .env.sh`
88
- ```
89
-
90
- Inside `.env.sh`, add a personal acccess token for the `CHANGELOG_GITLAB_TOKEN`
91
- environment variable. Next source the file:
92
-
93
- ```console
94
- . .env.sh
95
- ```
96
-
97
83
  ### Releasing a new version
98
84
 
99
- Releasing a new version can be done by pushing a new tag, or creating
100
- it from the
101
- [interface](https://gitlab.com/gitlab-org/labkit-ruby/-/tags).
102
-
103
- A new changelog will automatically be added to the release on Gitlab.
85
+ Releases are cut automatically by
86
+ [semantic-release](https://github.com/semantic-release/semantic-release)
87
+ when changes are merged to `master` or to an `N-N-stable` branch. The
88
+ [Conventional Commits](https://www.conventionalcommits.org/) type of each
89
+ commit decides the version bump (see [AGENTS.md](AGENTS.md)), and the
90
+ release notes are generated from those commit messages.
104
91
 
105
92
  The new version will automatically be published to `gitlab-labkit` on
106
93
  [rubygems](https://rubygems.org/gems/gitlab-labkit) when the pipeline
@@ -66,7 +66,7 @@ Labkit::JsonSchema::RefResolver.cache.clear
66
66
 
67
67
  ## Use Case Example
68
68
 
69
- The `RefResolver` is used in the User Experience SLI Registry [lib/labkit/user_experience_sli/registry.rb](lib/labkit/user_experience_sli/registry.rb) to validate user experience definitions against a JSON schema.
69
+ The `RefResolver` is used in the User Experience SLI Registry [lib/labkit/user_experience_sli/registry.rb](../user_experience_sli/registry.rb) to validate user experience definitions against a JSON schema.
70
70
 
71
71
  ## Implementation Details
72
72
 
@@ -173,7 +173,7 @@ RSpec::Matchers.define :complete_user_experience do |user_experience_id, error:
173
173
  "Failed to complete user experience '#{user_experience_id}':\n" \
174
174
  "expected checkpoint='end' counter to increase by 1, but increased by #{@checkpoint_change}\n" \
175
175
  "expected total='error: #{error}' counter to increase by 1, but increased by #{@total_change}\n" \
176
- "expected apdex='success: #{success}' counter to increase by 1, but increased by #{@apdex_change}"
176
+ "expected apdex='success: #{success}' counter to increase by #{error ? 0 : 1}, but increased by #{@apdex_change}"
177
177
  end
178
178
 
179
179
  match_when_negated do |actual|
@@ -192,7 +192,7 @@ RSpec::Matchers.define :complete_user_experience do |user_experience_id, error:
192
192
  @total_change = total_after - total_before
193
193
  @apdex_change = apdex_after - apdex_before
194
194
 
195
- @checkpoint_change.zero? && @total_change.zero? && @apdex_change == (error ? 1 : 0)
195
+ @checkpoint_change.zero? && @total_change.zero? && @apdex_change.zero?
196
196
  end
197
197
 
198
198
  failure_message_when_negated do
data/performance.yml ADDED
@@ -0,0 +1,70 @@
1
+ # Performance contract for labkit-ruby
2
+ # https://handbook.gitlab.com/handbook/engineering/testing/performance-contracts/
3
+ #
4
+ # This file is the single entry point for performance contract tooling.
5
+ # Customize the sections relevant to your service and remove the rest.
6
+ # Schema reference: https://handbook.gitlab.com/handbook/engineering/testing/performance-contracts/#schema-definition
7
+
8
+ version: "1.0"
9
+ service:
10
+ name: "labkit-ruby"
11
+ description: "Performance contract for labkit-ruby"
12
+
13
+ # ---------------------------------------------------------------------------
14
+ # Frontend / UI contracts (SiteSpeed)
15
+ # Uncomment and configure if this service has a frontend component.
16
+ # Budget files live in the sitespeed-measurement-setup submodule.
17
+ # ---------------------------------------------------------------------------
18
+ # frontend:
19
+ # enabled: true
20
+ # budgets:
21
+ # production: testrunner/sitespeed-measurement-setup/performance/budgets/environments/production.json
22
+ # staging: testrunner/sitespeed-measurement-setup/performance/budgets/environments/staging.json
23
+ # mr: testrunner/sitespeed-measurement-setup/performance/budgets/environments/mr.json
24
+ # teams:
25
+ # labkit-ruby:
26
+ # url_dir: testrunner/sitespeed-measurement-setup/gitlab/desktop/urls
27
+ # budget: testrunner/sitespeed-measurement-setup/performance/budgets/teams/labkit-ruby.json
28
+ # default_budget: mr
29
+
30
+ # ---------------------------------------------------------------------------
31
+ # Backend / Service contracts (k6 / CPT)
32
+ # Define endpoint categories with latency and error-rate targets.
33
+ # Choose a tier as a starting point, then tune from baseline data.
34
+ #
35
+ # Tier 1 (fast reads): p95=100ms, p99=250ms, error_rate=0.001
36
+ # Tier 2 (std reads): p95=500ms, p99=1000ms, error_rate=0.005
37
+ # Tier 3 (writes): p95=1500ms, p99=3000ms, error_rate=0.01
38
+ # Tier 4 (git ops): p95=5000ms, p99=10000ms,error_rate=0.001
39
+ # ---------------------------------------------------------------------------
40
+ # endpoints:
41
+ # fast_reads:
42
+ # description: >
43
+ # Single item lookup by ID. Simulates one indexed DB read.
44
+ # routes:
45
+ # - "GET /api/v1/items/{id}"
46
+ # metrics:
47
+ # latency_p95_ms: 100
48
+ # latency_p99_ms: 250
49
+ # error_rate_threshold: 0.001
50
+
51
+ # ---------------------------------------------------------------------------
52
+ # Resource budgets (informational; enforcement planned for a future iteration)
53
+ # ---------------------------------------------------------------------------
54
+ # resources:
55
+ # memory_limit_mb: 256
56
+ # cpu_limit_cores: 0.5
57
+ # connection_pool_max: 10
58
+
59
+ # ---------------------------------------------------------------------------
60
+ # SLI mapping -- links contract endpoints to Prometheus metrics emitted by
61
+ # LabKit v2. Fill in once your service is instrumented.
62
+ # ---------------------------------------------------------------------------
63
+ # sli_mapping:
64
+ # metrics_namespace: gitlab
65
+ # component: labkit-ruby
66
+ # fast_reads:
67
+ # requests_total_metric: gitlab_http_requests_total
68
+ # duration_metric: gitlab_http_request_duration_seconds
69
+ # endpoint_id_label: "GET /api/v1/items/{id}"
70
+ # feature_category_label: labkit_ruby
@@ -21,6 +21,28 @@ warn() {
21
21
  echo >&2 -e "Recommended reading: https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md"
22
22
  }
23
23
 
24
+ # `mise plugins update` contacts GitHub for every registered plugin: slow, and
25
+ # it adds up when many vendored copies of this script run across many projects
26
+ # on the same machine. Throttle it to once a day using a stamp file in the
27
+ # user's cache directory, deliberately outside the project so that the throttle
28
+ # is shared by every project that vendors this script.
29
+ mise_plugins_update() {
30
+ local stamp_dir="${XDG_CACHE_HOME:-${HOME:-}/.cache}/common-template-copier"
31
+ local stamp_file="${stamp_dir}/mise-plugins-update"
32
+
33
+ # `find -mtime -1` rather than `stat`, which is spelled differently on
34
+ # GNU/BSD. It prints nothing when the stamp is missing or over a day old.
35
+ if [[ -z ${FORCE_MISE_PLUGINS_UPDATE-} ]] && [[ -n $(find "$stamp_file" -mtime -1 2>/dev/null) ]]; then
36
+ echo >&2 "skipping 'mise plugins update' (ran in the last 24h; set FORCE_MISE_PLUGINS_UPDATE=1 to force)"
37
+ return 0
38
+ fi
39
+
40
+ mise plugins update -q
41
+
42
+ # Best effort: a machine without a writable cache dir just updates every time.
43
+ mkdir -p "$stamp_dir" && touch "$stamp_file" || true
44
+ }
45
+
24
46
  if command -v mise >/dev/null; then
25
47
  echo >&2 -e "mise installed..."
26
48
  elif command -v rtx >/dev/null; then
@@ -53,8 +75,8 @@ fi
53
75
 
54
76
  # install mise/asdf dependencies
55
77
  echo "installing required plugins with mise install.."
56
- mise plugins update -q
57
78
  mise trust --yes
79
+ mise_plugins_update
58
80
  mise install
59
81
 
60
82
  # set PROMPT_COMMAND to empty value for mise if unset
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-labkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.0
4
+ version: 5.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Newdigate
@@ -562,9 +562,10 @@ executables:
562
562
  extensions: []
563
563
  extra_rdoc_files: []
564
564
  files:
565
+ - ".claude/hooks/precommit-validate.sh"
566
+ - ".claude/settings.json"
565
567
  - ".copier-answers.yml"
566
568
  - ".editorconfig"
567
- - ".env.example.sh"
568
569
  - ".gitignore"
569
570
  - ".gitlab-ci-asdf-versions.yml"
570
571
  - ".gitlab-ci-other-versions.yml"
@@ -574,6 +575,7 @@ files:
574
575
  - ".gitlab/merge_request_templates/default.md"
575
576
  - ".gitleaks.toml"
576
577
  - ".mise.toml"
578
+ - ".opencode/plugins/precommit-validate.ts"
577
579
  - ".pre-commit-config.yaml"
578
580
  - ".releaserc.json"
579
581
  - ".rspec"
@@ -583,6 +585,7 @@ files:
583
585
  - ".tool-versions"
584
586
  - ".yamllint.yaml"
585
587
  - AGENTS.md
588
+ - CLAUDE.md
586
589
  - CODEOWNERS
587
590
  - CONTRIBUTING.md
588
591
  - Dangerfile
@@ -712,6 +715,7 @@ files:
712
715
  - lib/labkit/user_experience_sli/experience.rb
713
716
  - lib/labkit/user_experience_sli/null.rb
714
717
  - lib/labkit/user_experience_sli/registry.rb
718
+ - performance.yml
715
719
  - renovate.json
716
720
  - scripts/prepare-dev-env.sh
717
721
  - scripts/update-asdf-version-variables.sh
data/.env.example.sh DELETED
@@ -1,7 +0,0 @@
1
- export CI_PROJECT_ID=10947578
2
- export CI_API_V4_URL="https://gitlab.com/api/v4"
3
- export CI_PROJECT_URL="https://gitlab.com/gitlab-org/ruby/gems/labkit-ruby"
4
- # Don't keep secrets in plaintext files. Use a keyring or 1password to load
5
- # it instead and export it as an env var.
6
- token=$(load-your-token)
7
- export GITLAB_TOKEN=$token