gitlab-labkit 0.37.0 → 0.39.0

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.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # LabKit-Ruby 🔬🔬🔬🔬🔬
1
+ # LabKit-Ruby 🔬🔬🔬🔬🔬
2
2
 
3
3
  LabKit-Ruby is minimalist library to provide functionality for Ruby services at GitLab.
4
4
 
@@ -22,6 +22,7 @@ LabKit-Ruby provides functionality in a number of areas:
22
22
  1. `Labkit::Correlation` For accessing the correlation id. (Generated and propagated by `Labkit::Context`)
23
23
  1. `Labkit::FIPS` for checking for FIPS mode and using FIPS-compliant algorithms.
24
24
  1. `Labkit::Logging` for sanitizing log messages.
25
+ 1. `Labkit::Metrics` for metrics. More on the [README](./lib/labkit/metrics/README.md).
25
26
  1. `Labkit::Tracing` for handling and propagating distributed traces.
26
27
 
27
28
  ## Developing
@@ -40,8 +41,6 @@ $ # Run tests, linters
40
41
  $ bundle exec rake verify
41
42
  ```
42
43
 
43
- Note that LabKit-Ruby uses the [`rufo`](https://github.com/ruby-formatter/rufo) for auto-formatting. Please run `bundle exec rake fix` to auto-format your code before pushing.
44
-
45
44
  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.
46
45
 
47
46
  To work on some of the scripts we use for releasing a new version,
@@ -51,7 +50,7 @@ make sure to add a new `.env.sh`.
51
50
  cp .env.example.sh .env.sh`
52
51
  ```
53
52
 
54
- Inside `.env.sh`, add a personal acccess token for the `GITLAB_TOKEN`
53
+ Inside `.env.sh`, add a personal acccess token for the `CHANGELOG_GITLAB_TOKEN`
55
54
  environment variable. Next source the file:
56
55
 
57
56
  ```console
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rufo"
5
4
 
6
5
  require "rspec/core/rake_task"
7
6
  RSpec::Core::RakeTask.new(:spec)
@@ -11,27 +10,9 @@ RuboCop::RakeTask.new(:rubocop) do |task|
11
10
  task.options = %w[--parallel]
12
11
  end
13
12
 
14
- desc "Alias for `rake rufo:run`"
15
- task :format => ["rufo:run"]
16
-
17
- namespace :rufo do
18
- require "rufo"
19
-
20
- def rufo_command(*switches, rake_args)
21
- files_or_dirs = rake_args[:files_or_dirs] || "."
22
- args = switches + files_or_dirs.split(" ")
23
- Rufo::Command.run(args)
24
- end
25
-
26
- desc "Format Ruby code in current directory"
27
- task :run, [:files_or_dirs] do |_task, rake_args|
28
- rufo_command(rake_args)
29
- end
30
-
31
- desc "Check that no formatting changes are produced"
32
- task :check, [:files_or_dirs] do |_task, rake_args|
33
- rufo_command("--check", rake_args)
34
- end
13
+ desc "update the rubocop todo config"
14
+ RuboCop::RakeTask.new("rubocop:config") do |task|
15
+ task.options = %w[--auto-gen-config]
35
16
  end
36
17
 
37
18
  desc "Generate test protobuf stubs"
@@ -40,8 +21,17 @@ task :gen_test_proto do
40
21
  Rufo::Command.run(["spec/support/grpc_service/test_pb.rb", "spec/support/grpc_service/test_services_pb.rb"])
41
22
  end
42
23
 
43
- task :fix => %w[rufo:run rubocop:auto_correct]
24
+ task :fix => ["rubocop:autocorrect"]
44
25
 
45
- task :verify => %w[spec rufo:check rubocop]
26
+ task :verify => %w[spec rubocop]
46
27
 
47
28
  task :default => %w[verify build]
29
+
30
+ desc "Start an IRB console with gem pre-loaded"
31
+ task :console do
32
+ $LOAD_PATH.unshift(File.expand_path("lib", __dir__))
33
+ require "irb"
34
+ require "gitlab-labkit"
35
+ ARGV.clear
36
+ IRB.start
37
+ end
@@ -5,7 +5,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "gitlab-labkit"
8
- spec.version = `git describe --tags`.chomp.gsub(/^v/, "")
8
+ version = ENV["CI_COMMIT_TAG"] || `git describe --tag --match "v[0-9]*.[0-9]*.[0-9]*"`
9
+ spec.version = version.chomp.gsub(/^v/, "")
9
10
  spec.authors = ["Andrew Newdigate"]
10
11
  spec.email = ["andrew@gitlab.com"]
11
12
 
@@ -16,32 +17,35 @@ Gem::Specification.new do |spec|
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|tools)/}) }
18
19
  spec.require_paths = ["lib"]
19
- spec.required_ruby_version = ">= 2.6.0"
20
+ spec.required_ruby_version = "~> 3.2"
20
21
 
21
22
  # Please maintain alphabetical order for dependencies
22
23
  spec.add_runtime_dependency "actionpack", ">= 5.0.0", "< 8.1.0"
23
24
  spec.add_runtime_dependency "activesupport", ">= 5.0.0", "< 8.1.0"
24
25
  spec.add_runtime_dependency "grpc", ">= 1.62" # Be sure to update the "grpc-tools" dev_dependency too
26
+ spec.add_runtime_dependency "google-protobuf", "~> 3" # Keep the major version to 3 until we update the `grpc` gem
25
27
  spec.add_runtime_dependency "jaeger-client", "~> 1.1.0"
26
28
  spec.add_runtime_dependency "opentracing", "~> 0.4"
27
- spec.add_runtime_dependency "pg_query", ">= 5.1.0", "< 7.0"
29
+ spec.add_runtime_dependency "pg_query", ">= 6.1.0", "< 7.0"
30
+ spec.add_runtime_dependency "prometheus-client-mmap", "~> 1.2.9"
28
31
  spec.add_runtime_dependency "redis", "> 3.0.0", "< 6.0.0"
29
32
 
30
33
  # Please maintain alphabetical order for dev dependencies
31
34
  spec.add_development_dependency "excon", "~> 0.78.1"
32
35
  spec.add_development_dependency "faraday", "~> 1.10.3"
33
36
  spec.add_development_dependency "gitlab-dangerfiles", "~> 2.11.0"
34
- spec.add_development_dependency "gitlab-styles", "~> 6.2.0"
37
+ spec.add_development_dependency "gitlab-styles", "~> 13.0.2"
35
38
  spec.add_development_dependency "grpc-tools", ">= 1.62"
36
- spec.add_development_dependency "httparty", "~> 0.17.3"
37
- spec.add_development_dependency "httpclient", "~> 2.8.3"
39
+ spec.add_development_dependency "httparty", "~> 0.22.0"
40
+ spec.add_development_dependency "httpclient", "~> 2.9.0"
41
+ spec.add_development_dependency "irb", "~> 1.15.2"
38
42
  spec.add_development_dependency "pry", "~> 0.12"
43
+ spec.add_development_dependency "pry-byebug", "~> 3.11"
39
44
  spec.add_development_dependency "rack", "~> 2.0"
40
- spec.add_development_dependency "rake", "~> 12.3"
45
+ spec.add_development_dependency "rake", "~> 13.2"
41
46
  spec.add_development_dependency "rest-client", "~> 2.1.0"
42
47
  spec.add_development_dependency "rspec", "~> 3.12.0"
43
48
  spec.add_development_dependency "rspec-parameterized", "~> 1.0"
44
- spec.add_development_dependency "rufo", "0.9.0"
45
49
  spec.add_development_dependency "sidekiq", ">= 5.2", "< 7"
46
50
  spec.add_development_dependency "webrick", "~> 1.7.0"
47
51
  end
data/lib/gitlab-labkit.rb CHANGED
@@ -12,6 +12,7 @@ module Labkit
12
12
  autoload :FIPS, "labkit/fips"
13
13
  autoload :Tracing, "labkit/tracing"
14
14
  autoload :Logging, "labkit/logging"
15
+ autoload :Metrics, "labkit/metrics"
15
16
  autoload :Middleware, "labkit/middleware"
16
17
 
17
18
  # Publishers to publish notifications whenever a HTTP reqeust is made.
@@ -0,0 +1,98 @@
1
+ # Labkit::Metrics
2
+
3
+ ## Usage
4
+
5
+ ```ruby
6
+ # create a new counter metric and returns it
7
+ http_requests = Labkit::Metrics::Client.counter(:http_requests, 'A counter of HTTP requests made')
8
+ # start using the counter
9
+ http_requests.increment
10
+
11
+ # resets the registry and reinitializes all metrics files
12
+ Labkit::Metrics::Client.reset!
13
+
14
+ # retrieves the metric (be it a counter, gauge, histogram, summary)
15
+ http_requests = Labkit::Metrics::Client.get(:http_requests)
16
+ ```
17
+
18
+ ### Counter
19
+
20
+ ```ruby
21
+ counter = Labkit::Metrics::Client.counter(:service_requests_total, '...')
22
+
23
+ # increment the counter for a given label set
24
+ counter.increment({ service: 'foo' })
25
+
26
+ # increment by a given value
27
+ counter.increment({ service: 'bar' }, 5)
28
+
29
+ # get current value for a given label set
30
+ counter.get({ service: 'bar' })
31
+ # => 5
32
+ ```
33
+
34
+ ### Gauge
35
+
36
+ ```ruby
37
+ gauge = Labkit::Metrics::Client.gauge(:room_temperature_celsius, '...')
38
+
39
+ # set a value
40
+ gauge.set({ room: 'kitchen' }, 21.534)
41
+
42
+ # retrieve the current value for a given label set
43
+ gauge.get({ room: 'kitchen' })
44
+ # => 21.534
45
+ ```
46
+
47
+ ### Histogram
48
+
49
+ ```ruby
50
+ histogram = Labkit::Metrics::Client.histogram(:service_latency_seconds, '...')
51
+
52
+ # record a value
53
+ histogram.observe({ service: 'users' }, Benchmark.realtime { service.call(arg) })
54
+
55
+ # retrieve the current bucket values
56
+ histogram.get({ service: 'users' })
57
+ # => { 0.005 => 3, 0.01 => 15, 0.025 => 18, ..., 2.5 => 42, 5 => 42, 10 => 42 }
58
+ ```
59
+
60
+ ### Summary
61
+
62
+ ```ruby
63
+ summary = Labkit::Metrics::Client.summary(:service_latency_seconds, '...')
64
+
65
+ # record a value
66
+ summary.observe({ service: 'database' }, Benchmark.realtime { service.call() })
67
+
68
+ # retrieve the current quantile values
69
+ summary.get({ service: 'database' })
70
+ # => { 0.5 => 0.1233122, 0.9 => 3.4323, 0.99 => 5.3428231 }
71
+ ```
72
+
73
+ ## Rack middleware
74
+
75
+ ```ruby
76
+ # config.ru
77
+
78
+ require 'rack'
79
+ require 'labkit/metrics/rack_exporter'
80
+
81
+ use Labkit::Metrics::RackExporter
82
+
83
+ run ->(env) { [200, {'Content-Type' => 'text/html'}, ['OK']] }
84
+ ```
85
+
86
+ ## Configuration
87
+
88
+ ```ruby
89
+ # config/initializers/metrics.rb
90
+
91
+ Labkit::Metrics::Client.reinitialize_on_pid_change(force: true)
92
+
93
+ Labkit::Metrics::Client.configure do |config|
94
+ config.logger = Gitlab::AppLogger
95
+ config.multiprocess_files_dir = 'tmp/prometheus_multiproc_dir'
96
+ config.pid_provider = ::Prometheus::PidProvider.method(:worker_id)
97
+ end
98
+ ```
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "singleton"
5
+ require 'concurrent-ruby'
6
+ require "prometheus/client"
7
+ require "labkit/metrics/registry"
8
+ require "labkit/metrics/null"
9
+
10
+ module Labkit
11
+ module Metrics
12
+ InvalidLabelSet = Class.new(RuntimeError)
13
+
14
+ # A thin wrapper around Prometheus::Client from the prometheus-client-mmap gem
15
+ # https://gitlab.com/gitlab-org/ruby/gems/prometheus-client-mmap
16
+ class Client
17
+ include Singleton
18
+ extend Forwardable
19
+
20
+ def_delegators :wrapped_client, :configure, :reinitialize_on_pid_change, :configuration
21
+
22
+ def initialize
23
+ @enabled = Concurrent::AtomicBoolean.new(true)
24
+ end
25
+
26
+ def wrapped_client
27
+ @client ||= ::Prometheus::Client
28
+ end
29
+
30
+ def disable!
31
+ @enabled.make_false
32
+ end
33
+
34
+ def enable!
35
+ @enabled.make_true
36
+ end
37
+
38
+ def enabled?
39
+ @enabled.true? && metrics_folder_present?
40
+ end
41
+
42
+ def safe_provide_metric(metric_type, name, *args)
43
+ return Null.instance unless enabled?
44
+
45
+ Registry.safe_register(metric_type, name, *args)
46
+ end
47
+
48
+ def metrics_folder_present?
49
+ dir = configuration.multiprocess_files_dir
50
+ dir && Dir.exist?(dir) && File.writable?(dir)
51
+ end
52
+
53
+ def counter(name, docstring, base_labels = {})
54
+ safe_provide_metric(:counter, name, docstring, base_labels)
55
+ end
56
+
57
+ def summary(name, docstring, base_labels = {})
58
+ safe_provide_metric(:summary, name, docstring, base_labels)
59
+ end
60
+
61
+ def histogram(
62
+ name, docstring, base_labels = {},
63
+ buckets = Prometheus::Client::Histogram::DEFAULT_BUCKETS)
64
+ safe_provide_metric(:histogram, name, docstring, base_labels, buckets)
65
+ end
66
+
67
+ def gauge(name, docstring, base_labels = {}, multiprocess_mode = :all)
68
+ safe_provide_metric(:gauge, name, docstring, base_labels, multiprocess_mode)
69
+ end
70
+
71
+ def reset!
72
+ Registry.reset!
73
+ end
74
+
75
+ def get(metric_name)
76
+ Registry.get(metric_name)
77
+ end
78
+
79
+ class << self
80
+ extend Forwardable
81
+
82
+ def_delegators :instance,
83
+ :enable!, :disable!, :counter, :gauge, :histogram, :summary, :reset!, :enabled?,
84
+ :configure, :reinitialize_on_pid_change, :configuration, :get
85
+
86
+ private :instance
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Labkit
4
+ module Metrics
5
+ # Fakes Prometheus::Client::Metric and all derived metrics.
6
+ # Explicitly avoiding meta-programming to make interface more obvious to interact with.
7
+ class Null
8
+ include Singleton
9
+
10
+ attr_reader :name, :docstring, :base_labels
11
+
12
+ def get(*args); end
13
+ def set(*args); end
14
+ def increment(*args); end
15
+ def decrement(*args); end
16
+ def observe(*args); end
17
+ def values(*args); end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prometheus/client/rack/exporter"
4
+
5
+ module Labkit
6
+ module Metrics
7
+ # A wrapper around the Rack exporter middleware provided by
8
+ # prometheus-client-mmap gem
9
+ # https://gitlab.com/gitlab-org/ruby/gems/prometheus-client-mmap
10
+ class RackExporter < Prometheus::Client::Rack::Exporter; end
11
+ end
12
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prometheus/client"
4
+
5
+ module Labkit
6
+ module Metrics
7
+ InvalidMetricType = Class.new(StandardError)
8
+
9
+ # A thin wrapper around Prometheus::Client::Registry.
10
+ # It provides a thread-safe way to register metrics with the Prometheus registry.
11
+ class Registry
12
+ class << self
13
+ INIT_REGISTRY_MUTEX = Mutex.new
14
+ REGISTER_MUTEX = Mutex.new
15
+
16
+ # Registers a metric with the Prometheus registry in a thread-safe manner.
17
+ # If the metric already exists, it returns the existing metric.
18
+ # If the metric does not exist, it creates a new one.
19
+ # Each metric-name is only registered once for a type (counter, gauge, histogram, summary),
20
+ # even if multiple threads attempt to register the same metric simultaneously.
21
+ #
22
+ # @param metric_type [Symbol] The type of metric to register (:counter, :gauge, :histogram, :summary)
23
+ # @param name [Symbol, String] The name of the metric
24
+ # @param args [Array] Additional arguments to pass to the metric constructor
25
+ # @return [Prometheus::Client::Metric] The registered metric
26
+ # @raise [InvalidMetricType] If the metric_type is not supported
27
+ #
28
+ # @example
29
+ # # Register a counter
30
+ # counter = Registry.safe_register(:counter, :http_requests_total, 'Total HTTP requests')
31
+ def safe_register(metric_type, name, *args)
32
+ REGISTER_MUTEX.synchronize do
33
+ get(name) || wrapped_registry.method(metric_type).call(name, *args)
34
+ end
35
+ end
36
+
37
+ # Cleans up the Prometheus registry and resets it to a new state.
38
+ def reset!
39
+ INIT_REGISTRY_MUTEX.synchronize do
40
+ Prometheus::Client.cleanup!
41
+ Prometheus::Client.reset!
42
+ @registry = nil
43
+ end
44
+ end
45
+
46
+ # Returns the metric for the given name from the Prometheus registry.
47
+ #
48
+ # @param metric_name [Symbol, String] The name of the metric
49
+ # @return [Prometheus::Client::Metric, nil] The registered metric or nil if it does not exist
50
+ def get(metric_name)
51
+ wrapped_registry.get(metric_name)
52
+ end
53
+
54
+ private
55
+
56
+ def wrapped_registry
57
+ @registry ||= init_registry
58
+ end
59
+
60
+ def init_registry
61
+ # Prometheus::Client.registry initializes a new registry with an underlying hash
62
+ # storing metrics and a mutex synchronizing the writes to that hash.
63
+ # This means we need to make sure we only build one registry, for accessing from within Labkit.
64
+ INIT_REGISTRY_MUTEX.synchronize { Prometheus::Client.registry }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "prometheus/client/formats/text"
4
+
5
+ module Labkit
6
+ # Metrics provides functionality for producing metrics
7
+ module Metrics
8
+ autoload :Client, "labkit/metrics/client"
9
+ autoload :RackExporter, "labkit/metrics/rack_exporter"
10
+ autoload :Null, "labkit/metrics/null"
11
+
12
+ class << self
13
+ def prometheus_metrics_text
14
+ dir = Client.configuration.multiprocess_files_dir
15
+ ::Prometheus::Client::Formats::Text.marshal_multiprocess(dir)
16
+ end
17
+ end
18
+ end
19
+ end
data/renovate.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
+ "extends": [
4
+ "gitlab>gitlab-com/gl-infra/common-ci-tasks:renovate-common",
5
+ "gitlab>gitlab-com/gl-infra/common-ci-tasks:renovate-truncated-versions"
6
+ ]
7
+ }
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env bash
2
+ # Vendored from https://gitlab.com/gitlab-com/gl-infra/common-template-copier
3
+ # Consider contributing upstream when updating this file
4
+
5
+ # This file is deprecated: going forward running `mise install` should be sufficient.
6
+
7
+ set -euo pipefail
8
+ IFS=$'\n\t'
9
+
10
+ echo >&2 -e "2024-08-07: this file is deprecated: going forward, simply run 'mise install' to install plugins."
11
+ echo >&2 -e "Recommended reading: https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md"
12
+
13
+ mise install
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+ # Vendored from https://gitlab.com/gitlab-com/gl-infra/common-template-copier
3
+ # Consider contributing upstream when updating this file
4
+
5
+ set -euo pipefail
6
+
7
+ # ---------------------------------------------------------
8
+ # This script will prepare your development environment
9
+ # while working on this project. Run it after cloning this
10
+ # project.
11
+ #
12
+ # It's recommended that you review
13
+ # https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md
14
+ # first.
15
+ # ---------------------------------------------------------
16
+
17
+ cd "$(dirname "${BASH_SOURCE[0]}")/.."
18
+
19
+ warn() {
20
+ echo >&2 -e "${1-}"
21
+ echo >&2 -e "Recommended reading: https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md"
22
+ }
23
+
24
+ if command -v mise >/dev/null; then
25
+ echo >&2 -e "mise installed..."
26
+ elif command -v rtx >/dev/null; then
27
+ warn "⚠️ 2024-01-02: 'rtx' has changed to 'mise'; please replace 'rtx' with 'mise'"
28
+ exit 1
29
+ elif [[ -n ${ASDF_DIR-} ]]; then
30
+ warn "⚠️ 2024-08-07: 'asdf' is no longer supported; please uninstall and replace with 'mise'"
31
+ exit 1
32
+ else
33
+ warn "mise is not installed."
34
+ exit 1
35
+ fi
36
+
37
+ # Do some validation to ensure that the environment is not misconfigured, as this may
38
+ # save a bunch of debugging effort down the line.
39
+
40
+ # Detect Rosetta 2
41
+ if [[ $(uname -m) == "arm64" ]] && [[ $(uname -p) == "x86_64" ]]; then
42
+ echo "This shell is running in Rosetta emulating x86_64. Please use native mode Apple Silicon." >&2
43
+ echo "For help visit https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md" >&2
44
+ exit 1
45
+ fi
46
+
47
+ # Detect ancient versions of bash
48
+ if ((BASH_VERSINFO[0] < 4)); then
49
+ echo "You're running bash < v4.0.0. Please upgrade to a newer version." >&2
50
+ echo "For help visit https://gitlab.com/gitlab-com/gl-infra/common-ci-tasks/-/blob/main/docs/developer-setup.md" >&2
51
+ exit 1
52
+ fi
53
+
54
+ # install mise/asdf dependencies
55
+ echo "installing required plugins with mise install.."
56
+ mise plugins update
57
+ mise install
58
+ eval "$(mise activate bash)"
59
+
60
+ # pre-commit is optional
61
+ if command -v pre-commit &>/dev/null; then
62
+ echo "running pre-commit install..."
63
+ pre-commit install
64
+ pre-commit install-hooks
65
+ pre-commit install --hook-type commit-msg
66
+ else
67
+ warn "pre-commit is not installed. Skipping."
68
+ fi
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ # Vendored from https://gitlab.com/gitlab-com/gl-infra/common-template-copier
3
+ # Consider contributing upstream when updating this file
4
+
5
+ # See the README.md for details of how this script works
6
+
7
+ set -euo pipefail
8
+ IFS=$'\n\t'
9
+
10
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
11
+
12
+ export LANG=C LC_ALL=C
13
+
14
+ generate() {
15
+ sort "${ROOT_DIR}/.tool-versions" |
16
+ awk '
17
+ BEGIN {
18
+ print "# DO NOT MANUALLY EDIT; Run ./scripts/update-asdf-version-variables.sh to update this";
19
+ print "variables:"
20
+ }
21
+ {
22
+ if (!/^#/ && $1 != "" && $2 != "system") {
23
+ gsub("-", "_", $1);
24
+ print " GL_ASDF_" toupper($1) "_VERSION: \"" $2 "\""
25
+ }
26
+ }
27
+ '
28
+ }
29
+
30
+ generate >"${ROOT_DIR}/.gitlab-ci-asdf-versions.yml"