makit 0.0.167 → 0.0.169
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/README.md +41 -41
- data/exe/makit +5 -5
- data/lib/makit/apache.rb +28 -28
- data/lib/makit/auto.rb +48 -48
- data/lib/makit/azure/blob_storage.rb +257 -257
- data/lib/makit/azure/cli.rb +284 -284
- data/lib/makit/azure-pipelines.rb +187 -187
- data/lib/makit/cli/base.rb +17 -17
- data/lib/makit/cli/build_commands.rb +500 -500
- data/lib/makit/cli/generators/base_generator.rb +74 -74
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
- data/lib/makit/cli/generators/generator_factory.rb +49 -49
- data/lib/makit/cli/generators/node_generator.rb +50 -50
- data/lib/makit/cli/generators/ruby_generator.rb +77 -77
- data/lib/makit/cli/generators/rust_generator.rb +50 -50
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +41 -41
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
- data/lib/makit/cli/main.rb +78 -78
- data/lib/makit/cli/pipeline_commands.rb +311 -311
- data/lib/makit/cli/project_commands.rb +868 -868
- data/lib/makit/cli/repository_commands.rb +661 -661
- data/lib/makit/cli/strategy_commands.rb +207 -207
- data/lib/makit/cli/utility_commands.rb +521 -521
- data/lib/makit/commands/factory.rb +359 -359
- data/lib/makit/commands/middleware/base.rb +73 -73
- data/lib/makit/commands/middleware/cache.rb +248 -248
- data/lib/makit/commands/middleware/command_logger.rb +312 -312
- data/lib/makit/commands/middleware/validator.rb +269 -269
- data/lib/makit/commands/request.rb +316 -316
- data/lib/makit/commands/result.rb +323 -323
- data/lib/makit/commands/runner.rb +386 -386
- data/lib/makit/commands/strategies/base.rb +171 -171
- data/lib/makit/commands/strategies/child_process.rb +162 -162
- data/lib/makit/commands/strategies/factory.rb +136 -136
- data/lib/makit/commands/strategies/synchronous.rb +139 -139
- data/lib/makit/commands.rb +50 -50
- data/lib/makit/configuration/dotnet_project.rb +48 -48
- data/lib/makit/configuration/gitlab_helper.rb +61 -61
- data/lib/makit/configuration/project.rb +292 -292
- data/lib/makit/configuration/rakefile_helper.rb +43 -43
- data/lib/makit/configuration/step.rb +34 -34
- data/lib/makit/configuration/timeout.rb +74 -74
- data/lib/makit/configuration.rb +21 -21
- data/lib/makit/content/default_gitignore.rb +7 -7
- data/lib/makit/content/default_gitignore.txt +225 -225
- data/lib/makit/content/default_rakefile.rb +13 -13
- data/lib/makit/content/gem_rakefile.rb +16 -16
- data/lib/makit/context.rb +1 -1
- data/lib/makit/data.rb +49 -49
- data/lib/makit/directories.rb +170 -170
- data/lib/makit/directory.rb +262 -262
- data/lib/makit/docs/files.rb +89 -89
- data/lib/makit/docs/rake.rb +102 -102
- data/lib/makit/dotnet/cli.rb +224 -224
- data/lib/makit/dotnet/project.rb +217 -217
- data/lib/makit/dotnet/solution.rb +38 -38
- data/lib/makit/dotnet/solution_classlib.rb +239 -239
- data/lib/makit/dotnet/solution_console.rb +264 -264
- data/lib/makit/dotnet/solution_maui.rb +354 -354
- data/lib/makit/dotnet/solution_wasm.rb +275 -275
- data/lib/makit/dotnet/solution_wpf.rb +304 -304
- data/lib/makit/dotnet.rb +110 -110
- data/lib/makit/email.rb +90 -90
- data/lib/makit/environment.rb +142 -142
- data/lib/makit/examples/runner.rb +370 -370
- data/lib/makit/exceptions.rb +45 -45
- data/lib/makit/fileinfo.rb +32 -32
- data/lib/makit/files.rb +43 -43
- data/lib/makit/gems.rb +49 -49
- data/lib/makit/git/cli.rb +103 -103
- data/lib/makit/git/repository.rb +100 -100
- data/lib/makit/git.rb +104 -104
- data/lib/makit/github_actions.rb +202 -0
- data/lib/makit/gitlab/pipeline.rb +857 -857
- data/lib/makit/gitlab/pipeline_service_impl.rb +1535 -1535
- data/lib/makit/gitlab_runner.rb +59 -59
- data/lib/makit/humanize.rb +218 -218
- data/lib/makit/indexer.rb +47 -47
- data/lib/makit/io/filesystem.rb +111 -111
- data/lib/makit/io/filesystem_service_impl.rb +337 -337
- data/lib/makit/lint.rb +212 -212
- data/lib/makit/logging/configuration.rb +309 -309
- data/lib/makit/logging/format_registry.rb +84 -84
- data/lib/makit/logging/formatters/base.rb +39 -39
- data/lib/makit/logging/formatters/console_formatter.rb +140 -140
- data/lib/makit/logging/formatters/json_formatter.rb +65 -65
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
- data/lib/makit/logging/formatters/text_formatter.rb +64 -64
- data/lib/makit/logging/log_request.rb +119 -119
- data/lib/makit/logging/logger.rb +199 -199
- data/lib/makit/logging/sinks/base.rb +91 -91
- data/lib/makit/logging/sinks/console.rb +72 -72
- data/lib/makit/logging/sinks/file_sink.rb +92 -92
- data/lib/makit/logging/sinks/structured.rb +123 -123
- data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
- data/lib/makit/logging.rb +578 -578
- data/lib/makit/markdown.rb +75 -75
- data/lib/makit/mp/basic_object_mp.rb +17 -17
- data/lib/makit/mp/command_mp.rb +13 -13
- data/lib/makit/mp/command_request.mp.rb +17 -17
- data/lib/makit/mp/project_mp.rb +199 -199
- data/lib/makit/mp/string_mp.rb +205 -205
- data/lib/makit/nuget.rb +460 -454
- data/lib/makit/podman/podman.rb +458 -458
- data/lib/makit/podman/podman_service_impl.rb +1081 -1081
- data/lib/makit/port.rb +32 -32
- data/lib/makit/process.rb +377 -377
- data/lib/makit/protoc.rb +112 -112
- data/lib/makit/rake/cli.rb +196 -196
- data/lib/makit/rake/trace_controller.rb +174 -174
- data/lib/makit/rake.rb +81 -81
- data/lib/makit/ruby/cli.rb +185 -185
- data/lib/makit/ruby.rb +25 -25
- data/lib/makit/rubygems.rb +137 -137
- data/lib/makit/secrets/azure_key_vault.rb +322 -322
- data/lib/makit/secrets/azure_secrets.rb +221 -221
- data/lib/makit/secrets/local_secrets.rb +72 -72
- data/lib/makit/secrets/secrets_manager.rb +105 -105
- data/lib/makit/secrets.rb +96 -96
- data/lib/makit/serializer.rb +130 -130
- data/lib/makit/services/builder.rb +186 -186
- data/lib/makit/services/error_handler.rb +226 -226
- data/lib/makit/services/repository_manager.rb +367 -367
- data/lib/makit/services/validator.rb +112 -112
- data/lib/makit/setup/classlib.rb +101 -101
- data/lib/makit/setup/gem.rb +268 -268
- data/lib/makit/setup/pages.rb +11 -11
- data/lib/makit/setup/razorclasslib.rb +101 -101
- data/lib/makit/setup/runner.rb +54 -54
- data/lib/makit/setup.rb +5 -5
- data/lib/makit/show.rb +110 -110
- data/lib/makit/storage.rb +126 -126
- data/lib/makit/symbols.rb +175 -175
- data/lib/makit/task_info.rb +130 -130
- data/lib/makit/tasks/at_exit.rb +15 -15
- data/lib/makit/tasks/build.rb +22 -22
- data/lib/makit/tasks/bump.rb +7 -7
- data/lib/makit/tasks/clean.rb +13 -13
- data/lib/makit/tasks/configure.rb +10 -10
- data/lib/makit/tasks/format.rb +10 -10
- data/lib/makit/tasks/hook_manager.rb +443 -443
- data/lib/makit/tasks/info.rb +368 -368
- data/lib/makit/tasks/init.rb +49 -49
- data/lib/makit/tasks/integrate.rb +60 -60
- data/lib/makit/tasks/pull_incoming.rb +13 -13
- data/lib/makit/tasks/secrets.rb +7 -7
- data/lib/makit/tasks/setup.rb +16 -16
- data/lib/makit/tasks/sync.rb +14 -14
- data/lib/makit/tasks/tag.rb +27 -27
- data/lib/makit/tasks/task_monkey_patch.rb +81 -81
- data/lib/makit/tasks/test.rb +22 -22
- data/lib/makit/tasks/update.rb +21 -21
- data/lib/makit/tasks/version.rb +6 -6
- data/lib/makit/tasks.rb +24 -24
- data/lib/makit/test_cache.rb +239 -239
- data/lib/makit/tree.rb +37 -37
- data/lib/makit/v1/configuration/project_service_impl.rb +370 -370
- data/lib/makit/v1/git/git_repository_service_impl.rb +295 -295
- data/lib/makit/v1/makit.v1_pb.rb +35 -35
- data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
- data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -572
- data/lib/makit/version.rb +661 -661
- data/lib/makit/version_util.rb +21 -21
- data/lib/makit/wix.rb +95 -95
- data/lib/makit/yaml.rb +29 -29
- data/lib/makit/zip.rb +17 -17
- data/lib/makit copy.rb +44 -44
- data/lib/makit.rb +121 -120
- metadata +3 -2
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
module Makit
|
|
2
|
-
class AzurePipelines
|
|
3
|
-
def self.status(project_name: nil, org: nil, project: nil, pipeline_id: nil, pipeline_name: nil, pat: nil)
|
|
4
|
-
require "net/http"
|
|
5
|
-
require "uri"
|
|
6
|
-
require "json"
|
|
7
|
-
|
|
8
|
-
# Get organization and project from git remote or environment variables
|
|
9
|
-
git_remote = `git remote get-url origin 2>/dev/null`.strip
|
|
10
|
-
if git_remote =~ /dev\.azure\.com\/([^\/]+)\/([^\/]+)/
|
|
11
|
-
org ||= $1
|
|
12
|
-
project ||= $2
|
|
13
|
-
else
|
|
14
|
-
org ||= ENV["AZURE_DEVOPS_ORG"] || "DevOpsMusco"
|
|
15
|
-
project ||= ENV["AZURE_DEVOPS_PROJECT"] || "Design"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Pipeline ID can be set via environment variable, or we'll try to find it by name
|
|
19
|
-
pipeline_id ||= ENV["AZURE_PIPELINE_ID"]
|
|
20
|
-
pipeline_name ||= ENV["AZURE_PIPELINE_NAME"] || project_name
|
|
21
|
-
|
|
22
|
-
# Display values if show_value is available (from raykit)
|
|
23
|
-
if defined?(show_value)
|
|
24
|
-
show_value "Organization", org
|
|
25
|
-
show_value "Project", project
|
|
26
|
-
show_value "Pipeline", pipeline_name
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Try to get access token from parameter, environment variable, or Azure CLI
|
|
30
|
-
pat ||= ENV["AZURE_DEVOPS_PAT"]
|
|
31
|
-
if pat.nil? || pat.empty?
|
|
32
|
-
puts " AZURE_DEVOPS_PAT not set, attempting to use Azure CLI authentication..."
|
|
33
|
-
begin
|
|
34
|
-
# Get access token for Azure DevOps (resource ID: 499b84ac-1321-427f-aa5e-6d8b3c8c4123)
|
|
35
|
-
token_output = `az account get-access-token --resource 499b84ac-1321-427f-aa5e-6d8b3c8c4123 --query accessToken -o tsv 2>&1`
|
|
36
|
-
if $?.exitstatus == 0 && !token_output.strip.empty?
|
|
37
|
-
pat = token_output.strip
|
|
38
|
-
puts " Successfully obtained access token from Azure CLI"
|
|
39
|
-
else
|
|
40
|
-
raise "Azure CLI authentication failed"
|
|
41
|
-
end
|
|
42
|
-
rescue => e
|
|
43
|
-
puts " Error: Could not get access token from Azure CLI"
|
|
44
|
-
puts " Make sure you're logged in: az login"
|
|
45
|
-
puts " Or set AZURE_DEVOPS_PAT: export AZURE_DEVOPS_PAT=your_personal_access_token"
|
|
46
|
-
exit 1
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Helper lambda to set authorization header (Azure AD tokens can use Bearer, PAT uses Basic)
|
|
51
|
-
set_auth_header = lambda do |req, token|
|
|
52
|
-
# Azure AD tokens are typically longer and can use Bearer auth
|
|
53
|
-
# PAT tokens use Basic auth. Try Bearer first for longer tokens, Basic for shorter ones
|
|
54
|
-
if token.length > 100
|
|
55
|
-
req["Authorization"] = "Bearer #{token}"
|
|
56
|
-
else
|
|
57
|
-
req.basic_auth("", token)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# If pipeline ID is not set, try to find it by name
|
|
62
|
-
if pipeline_id.nil? || pipeline_id.empty?
|
|
63
|
-
puts " Looking up pipeline ID for '#{pipeline_name}'..."
|
|
64
|
-
uri = URI("https://dev.azure.com/#{org}/#{project}/_apis/pipelines?api-version=7.1")
|
|
65
|
-
req = Net::HTTP::Get.new(uri)
|
|
66
|
-
set_auth_header.call(req, pat)
|
|
67
|
-
req["Content-Type"] = "application/json"
|
|
68
|
-
|
|
69
|
-
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
70
|
-
http.request(req)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
if res.is_a?(Net::HTTPSuccess)
|
|
74
|
-
pipelines = JSON.parse(res.body)["value"]
|
|
75
|
-
pipeline = pipelines.find { |p| p["name"] == pipeline_name || p["name"].include?(pipeline_name) }
|
|
76
|
-
if pipeline
|
|
77
|
-
pipeline_id = pipeline["id"].to_s
|
|
78
|
-
puts " Found pipeline ID: #{pipeline_id}"
|
|
79
|
-
else
|
|
80
|
-
puts " Error: Could not find pipeline '#{pipeline_name}'"
|
|
81
|
-
puts " Available pipelines: #{pipelines.map { |p| p["name"] }.join(", ")}"
|
|
82
|
-
exit 1
|
|
83
|
-
end
|
|
84
|
-
else
|
|
85
|
-
puts " Error: Failed to list pipelines: #{res.code} #{res.message}"
|
|
86
|
-
exit 1
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Get the latest pipeline run
|
|
91
|
-
puts " Fetching latest pipeline run..."
|
|
92
|
-
uri = URI("https://dev.azure.com/#{org}/#{project}/_apis/pipelines/#{pipeline_id}/runs")
|
|
93
|
-
params = {
|
|
94
|
-
"$top" => 1,
|
|
95
|
-
"api-version" => "7.1",
|
|
96
|
-
}
|
|
97
|
-
uri.query = URI.encode_www_form(params)
|
|
98
|
-
|
|
99
|
-
req = Net::HTTP::Get.new(uri)
|
|
100
|
-
set_auth_header.call(req, pat)
|
|
101
|
-
req["Content-Type"] = "application/json"
|
|
102
|
-
|
|
103
|
-
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
104
|
-
http.request(req)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
if res.is_a?(Net::HTTPSuccess)
|
|
108
|
-
body = JSON.parse(res.body)
|
|
109
|
-
if body["value"] && body["value"].length > 0
|
|
110
|
-
run = body["value"].first
|
|
111
|
-
result = run["result"] || "unknown"
|
|
112
|
-
state = run["state"] || "unknown"
|
|
113
|
-
build_number = run["name"] || run["id"].to_s
|
|
114
|
-
finish_time = run["finishedDate"] || run["createdDate"] || "N/A"
|
|
115
|
-
url = run["_links"] && run["_links"]["web"] ? run["_links"]["web"]["href"] : "https://dev.azure.com/#{org}/#{project}/_build/results?buildId=#{run["id"]}"
|
|
116
|
-
|
|
117
|
-
puts " Latest Run:"
|
|
118
|
-
puts " Build Number: #{build_number}"
|
|
119
|
-
puts " State: #{state}"
|
|
120
|
-
puts " Result: #{result}"
|
|
121
|
-
puts " Finished: #{finish_time}"
|
|
122
|
-
puts " URL: #{url}"
|
|
123
|
-
else
|
|
124
|
-
puts " No pipeline runs found yet."
|
|
125
|
-
end
|
|
126
|
-
else
|
|
127
|
-
puts " Error: Failed to fetch pipeline runs: #{res.code} #{res.message}"
|
|
128
|
-
if res.body
|
|
129
|
-
error_body = JSON.parse(res.body) rescue nil
|
|
130
|
-
if error_body && error_body["message"]
|
|
131
|
-
puts " Message: #{error_body["message"]}"
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
exit 1
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
# Publishes a NuGet package to an Azure DevOps feed
|
|
138
|
-
#
|
|
139
|
-
# @param package_name [String] The name of the NuGet package
|
|
140
|
-
# @param package_version [String] The version of the package
|
|
141
|
-
# @param package_file [String] Path to the .nupkg file
|
|
142
|
-
# @param feed_source [String] The name of the Azure DevOps feed
|
|
143
|
-
# @param api_key [String, nil] Optional API key (defaults to "az" for Azure CLI)
|
|
144
|
-
# @raise [RuntimeError] If the push fails and it's not a duplicate package error
|
|
145
|
-
def self.publish(package_name:, package_version:, package_file:, feed_source:, api_key: "az")
|
|
146
|
-
puts " Checking if package #{package_name} version #{package_version} already exists in feed..."
|
|
147
|
-
|
|
148
|
-
# Check if package version already exists
|
|
149
|
-
list_command = "dotnet nuget list \"#{package_name}\" --source \"#{feed_source}\" --api-key #{api_key}"
|
|
150
|
-
list_output = `#{list_command} 2>&1`
|
|
151
|
-
list_exit_code = $?.exitstatus
|
|
152
|
-
|
|
153
|
-
if list_exit_code == 0 && list_output.include?(package_version)
|
|
154
|
-
puts " Package #{package_name} version #{package_version} already exists in feed. Skipping push."
|
|
155
|
-
elsif list_exit_code != 0 && list_output =~ /401|Unauthorized|credential/i
|
|
156
|
-
puts " Authentication failed when checking feed. Will attempt to push anyway."
|
|
157
|
-
puts " (To check manually, run: #{list_command} --interactive)"
|
|
158
|
-
push_package(package_file: package_file, feed_source: feed_source, api_key: api_key, package_name: package_name, package_version: package_version)
|
|
159
|
-
else
|
|
160
|
-
puts " Package #{package_name} version #{package_version} not found in feed (or unable to verify). Attempting to push..."
|
|
161
|
-
push_package(package_file: package_file, feed_source: feed_source, api_key: api_key, package_name: package_name, package_version: package_version)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
private
|
|
166
|
-
|
|
167
|
-
def self.push_package(package_file:, feed_source:, api_key:, package_name:, package_version:)
|
|
168
|
-
push_command = "dotnet nuget push \"#{package_file}\" --source \"#{feed_source}\" --api-key #{api_key} --skip-duplicate"
|
|
169
|
-
push_output = `#{push_command} 2>&1`
|
|
170
|
-
push_exit_code = $?.exitstatus
|
|
171
|
-
|
|
172
|
-
if push_exit_code == 0
|
|
173
|
-
puts " Package pushed successfully to #{feed_source} feed."
|
|
174
|
-
elsif push_output =~ /already exists|conflict|409/i
|
|
175
|
-
puts " Package #{package_name} version #{package_version} already exists in feed. This is expected."
|
|
176
|
-
else
|
|
177
|
-
puts " Error pushing package to #{feed_source} feed:"
|
|
178
|
-
puts push_output
|
|
179
|
-
puts ""
|
|
180
|
-
puts " To retry manually, run:"
|
|
181
|
-
puts " #{push_command} --interactive"
|
|
182
|
-
puts ""
|
|
183
|
-
raise "Failed to push package to #{feed_source} feed"
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
end
|
|
1
|
+
module Makit
|
|
2
|
+
class AzurePipelines
|
|
3
|
+
def self.status(project_name: nil, org: nil, project: nil, pipeline_id: nil, pipeline_name: nil, pat: nil)
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
require "json"
|
|
7
|
+
|
|
8
|
+
# Get organization and project from git remote or environment variables
|
|
9
|
+
git_remote = `git remote get-url origin 2>/dev/null`.strip
|
|
10
|
+
if git_remote =~ /dev\.azure\.com\/([^\/]+)\/([^\/]+)/
|
|
11
|
+
org ||= $1
|
|
12
|
+
project ||= $2
|
|
13
|
+
else
|
|
14
|
+
org ||= ENV["AZURE_DEVOPS_ORG"] || "DevOpsMusco"
|
|
15
|
+
project ||= ENV["AZURE_DEVOPS_PROJECT"] || "Design"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Pipeline ID can be set via environment variable, or we'll try to find it by name
|
|
19
|
+
pipeline_id ||= ENV["AZURE_PIPELINE_ID"]
|
|
20
|
+
pipeline_name ||= ENV["AZURE_PIPELINE_NAME"] || project_name
|
|
21
|
+
|
|
22
|
+
# Display values if show_value is available (from raykit)
|
|
23
|
+
if defined?(show_value)
|
|
24
|
+
show_value "Organization", org
|
|
25
|
+
show_value "Project", project
|
|
26
|
+
show_value "Pipeline", pipeline_name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Try to get access token from parameter, environment variable, or Azure CLI
|
|
30
|
+
pat ||= ENV["AZURE_DEVOPS_PAT"]
|
|
31
|
+
if pat.nil? || pat.empty?
|
|
32
|
+
puts " AZURE_DEVOPS_PAT not set, attempting to use Azure CLI authentication..."
|
|
33
|
+
begin
|
|
34
|
+
# Get access token for Azure DevOps (resource ID: 499b84ac-1321-427f-aa5e-6d8b3c8c4123)
|
|
35
|
+
token_output = `az account get-access-token --resource 499b84ac-1321-427f-aa5e-6d8b3c8c4123 --query accessToken -o tsv 2>&1`
|
|
36
|
+
if $?.exitstatus == 0 && !token_output.strip.empty?
|
|
37
|
+
pat = token_output.strip
|
|
38
|
+
puts " Successfully obtained access token from Azure CLI"
|
|
39
|
+
else
|
|
40
|
+
raise "Azure CLI authentication failed"
|
|
41
|
+
end
|
|
42
|
+
rescue => e
|
|
43
|
+
puts " Error: Could not get access token from Azure CLI"
|
|
44
|
+
puts " Make sure you're logged in: az login"
|
|
45
|
+
puts " Or set AZURE_DEVOPS_PAT: export AZURE_DEVOPS_PAT=your_personal_access_token"
|
|
46
|
+
exit 1
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Helper lambda to set authorization header (Azure AD tokens can use Bearer, PAT uses Basic)
|
|
51
|
+
set_auth_header = lambda do |req, token|
|
|
52
|
+
# Azure AD tokens are typically longer and can use Bearer auth
|
|
53
|
+
# PAT tokens use Basic auth. Try Bearer first for longer tokens, Basic for shorter ones
|
|
54
|
+
if token.length > 100
|
|
55
|
+
req["Authorization"] = "Bearer #{token}"
|
|
56
|
+
else
|
|
57
|
+
req.basic_auth("", token)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# If pipeline ID is not set, try to find it by name
|
|
62
|
+
if pipeline_id.nil? || pipeline_id.empty?
|
|
63
|
+
puts " Looking up pipeline ID for '#{pipeline_name}'..."
|
|
64
|
+
uri = URI("https://dev.azure.com/#{org}/#{project}/_apis/pipelines?api-version=7.1")
|
|
65
|
+
req = Net::HTTP::Get.new(uri)
|
|
66
|
+
set_auth_header.call(req, pat)
|
|
67
|
+
req["Content-Type"] = "application/json"
|
|
68
|
+
|
|
69
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
70
|
+
http.request(req)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if res.is_a?(Net::HTTPSuccess)
|
|
74
|
+
pipelines = JSON.parse(res.body)["value"]
|
|
75
|
+
pipeline = pipelines.find { |p| p["name"] == pipeline_name || p["name"].include?(pipeline_name) }
|
|
76
|
+
if pipeline
|
|
77
|
+
pipeline_id = pipeline["id"].to_s
|
|
78
|
+
puts " Found pipeline ID: #{pipeline_id}"
|
|
79
|
+
else
|
|
80
|
+
puts " Error: Could not find pipeline '#{pipeline_name}'"
|
|
81
|
+
puts " Available pipelines: #{pipelines.map { |p| p["name"] }.join(", ")}"
|
|
82
|
+
exit 1
|
|
83
|
+
end
|
|
84
|
+
else
|
|
85
|
+
puts " Error: Failed to list pipelines: #{res.code} #{res.message}"
|
|
86
|
+
exit 1
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Get the latest pipeline run
|
|
91
|
+
puts " Fetching latest pipeline run..."
|
|
92
|
+
uri = URI("https://dev.azure.com/#{org}/#{project}/_apis/pipelines/#{pipeline_id}/runs")
|
|
93
|
+
params = {
|
|
94
|
+
"$top" => 1,
|
|
95
|
+
"api-version" => "7.1",
|
|
96
|
+
}
|
|
97
|
+
uri.query = URI.encode_www_form(params)
|
|
98
|
+
|
|
99
|
+
req = Net::HTTP::Get.new(uri)
|
|
100
|
+
set_auth_header.call(req, pat)
|
|
101
|
+
req["Content-Type"] = "application/json"
|
|
102
|
+
|
|
103
|
+
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
104
|
+
http.request(req)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
if res.is_a?(Net::HTTPSuccess)
|
|
108
|
+
body = JSON.parse(res.body)
|
|
109
|
+
if body["value"] && body["value"].length > 0
|
|
110
|
+
run = body["value"].first
|
|
111
|
+
result = run["result"] || "unknown"
|
|
112
|
+
state = run["state"] || "unknown"
|
|
113
|
+
build_number = run["name"] || run["id"].to_s
|
|
114
|
+
finish_time = run["finishedDate"] || run["createdDate"] || "N/A"
|
|
115
|
+
url = run["_links"] && run["_links"]["web"] ? run["_links"]["web"]["href"] : "https://dev.azure.com/#{org}/#{project}/_build/results?buildId=#{run["id"]}"
|
|
116
|
+
|
|
117
|
+
puts " Latest Run:"
|
|
118
|
+
puts " Build Number: #{build_number}"
|
|
119
|
+
puts " State: #{state}"
|
|
120
|
+
puts " Result: #{result}"
|
|
121
|
+
puts " Finished: #{finish_time}"
|
|
122
|
+
puts " URL: #{url}"
|
|
123
|
+
else
|
|
124
|
+
puts " No pipeline runs found yet."
|
|
125
|
+
end
|
|
126
|
+
else
|
|
127
|
+
puts " Error: Failed to fetch pipeline runs: #{res.code} #{res.message}"
|
|
128
|
+
if res.body
|
|
129
|
+
error_body = JSON.parse(res.body) rescue nil
|
|
130
|
+
if error_body && error_body["message"]
|
|
131
|
+
puts " Message: #{error_body["message"]}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
exit 1
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
# Publishes a NuGet package to an Azure DevOps feed
|
|
138
|
+
#
|
|
139
|
+
# @param package_name [String] The name of the NuGet package
|
|
140
|
+
# @param package_version [String] The version of the package
|
|
141
|
+
# @param package_file [String] Path to the .nupkg file
|
|
142
|
+
# @param feed_source [String] The name of the Azure DevOps feed
|
|
143
|
+
# @param api_key [String, nil] Optional API key (defaults to "az" for Azure CLI)
|
|
144
|
+
# @raise [RuntimeError] If the push fails and it's not a duplicate package error
|
|
145
|
+
def self.publish(package_name:, package_version:, package_file:, feed_source:, api_key: "az")
|
|
146
|
+
puts " Checking if package #{package_name} version #{package_version} already exists in feed..."
|
|
147
|
+
|
|
148
|
+
# Check if package version already exists
|
|
149
|
+
list_command = "dotnet nuget list \"#{package_name}\" --source \"#{feed_source}\" --api-key #{api_key}"
|
|
150
|
+
list_output = `#{list_command} 2>&1`
|
|
151
|
+
list_exit_code = $?.exitstatus
|
|
152
|
+
|
|
153
|
+
if list_exit_code == 0 && list_output.include?(package_version)
|
|
154
|
+
puts " Package #{package_name} version #{package_version} already exists in feed. Skipping push."
|
|
155
|
+
elsif list_exit_code != 0 && list_output =~ /401|Unauthorized|credential/i
|
|
156
|
+
puts " Authentication failed when checking feed. Will attempt to push anyway."
|
|
157
|
+
puts " (To check manually, run: #{list_command} --interactive)"
|
|
158
|
+
push_package(package_file: package_file, feed_source: feed_source, api_key: api_key, package_name: package_name, package_version: package_version)
|
|
159
|
+
else
|
|
160
|
+
puts " Package #{package_name} version #{package_version} not found in feed (or unable to verify). Attempting to push..."
|
|
161
|
+
push_package(package_file: package_file, feed_source: feed_source, api_key: api_key, package_name: package_name, package_version: package_version)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def self.push_package(package_file:, feed_source:, api_key:, package_name:, package_version:)
|
|
168
|
+
push_command = "dotnet nuget push \"#{package_file}\" --source \"#{feed_source}\" --api-key #{api_key} --skip-duplicate"
|
|
169
|
+
push_output = `#{push_command} 2>&1`
|
|
170
|
+
push_exit_code = $?.exitstatus
|
|
171
|
+
|
|
172
|
+
if push_exit_code == 0
|
|
173
|
+
puts " Package pushed successfully to #{feed_source} feed."
|
|
174
|
+
elsif push_output =~ /already exists|conflict|409/i
|
|
175
|
+
puts " Package #{package_name} version #{package_version} already exists in feed. This is expected."
|
|
176
|
+
else
|
|
177
|
+
puts " Error pushing package to #{feed_source} feed:"
|
|
178
|
+
puts push_output
|
|
179
|
+
puts ""
|
|
180
|
+
puts " To retry manually, run:"
|
|
181
|
+
puts " #{push_command} --interactive"
|
|
182
|
+
puts ""
|
|
183
|
+
raise "Failed to push package to #{feed_source} feed"
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
188
|
|
data/lib/makit/cli/base.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "clamp"
|
|
4
|
-
|
|
5
|
-
module Makit
|
|
6
|
-
module Cli
|
|
7
|
-
# Base class for CLI commands
|
|
8
|
-
class Base < Clamp::Command
|
|
9
|
-
# Common functionality for CLI commands can be added here
|
|
10
|
-
|
|
11
|
-
# Helper method to define command descriptions
|
|
12
|
-
def self.desc(command_name, description)
|
|
13
|
-
self.description = "#{command_name} - #{description}"
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "clamp"
|
|
4
|
+
|
|
5
|
+
module Makit
|
|
6
|
+
module Cli
|
|
7
|
+
# Base class for CLI commands
|
|
8
|
+
class Base < Clamp::Command
|
|
9
|
+
# Common functionality for CLI commands can be added here
|
|
10
|
+
|
|
11
|
+
# Helper method to define command descriptions
|
|
12
|
+
def self.desc(command_name, description)
|
|
13
|
+
self.description = "#{command_name} - #{description}"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|