fastlane-plugin-circle_ci 0.2.0 → 0.3.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +272 -3
  3. data/lib/fastlane/plugin/circle_ci/actions/circleci_add_context_env_var.rb +117 -0
  4. data/lib/fastlane/plugin/circle_ci/actions/circleci_add_project_collaborator.rb +109 -0
  5. data/lib/fastlane/plugin/circle_ci/actions/circleci_approve_job.rb +95 -0
  6. data/lib/fastlane/plugin/circle_ci/actions/circleci_cancel_job.rb +96 -0
  7. data/lib/fastlane/plugin/circle_ci/actions/circleci_cancel_workflow.rb +85 -0
  8. data/lib/fastlane/plugin/circle_ci/actions/circleci_continue_pipeline.rb +104 -0
  9. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_checkout_key.rb +110 -0
  10. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_pipeline_definition.rb +126 -0
  11. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_pipeline_definition_trigger.rb +133 -0
  12. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_pipeline_schedule.rb +160 -0
  13. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_project.rb +105 -0
  14. data/lib/fastlane/plugin/circle_ci/actions/circleci_create_webhook.rb +155 -0
  15. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_checkout_key.rb +93 -0
  16. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_context_env_var.rb +110 -0
  17. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_env_var.rb +86 -0
  18. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_pipeline_definition.rb +91 -0
  19. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_pipeline_schedule.rb +95 -0
  20. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_trigger.rb +92 -0
  21. data/lib/fastlane/plugin/circle_ci/actions/circleci_delete_webhook.rb +86 -0
  22. data/lib/fastlane/plugin/circle_ci/actions/circleci_download_artifact.rb +119 -0
  23. data/lib/fastlane/plugin/circle_ci/actions/circleci_download_workflow_artifacts.rb +400 -0
  24. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_checkout_key.rb +101 -0
  25. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_checkout_keys.rb +96 -0
  26. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_context_env_vars.rb +114 -0
  27. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_env_vars.rb +95 -0
  28. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_flaky_tests.rb +99 -0
  29. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_job_artifacts.rb +111 -0
  30. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_job_details.rb +110 -0
  31. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_job_tests.rb +111 -0
  32. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_job_timeseries.rb +131 -0
  33. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_my_pipelines.rb +100 -0
  34. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_org_summary.rb +113 -0
  35. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline.rb +104 -0
  36. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_by_number.rb +105 -0
  37. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_config.rb +92 -0
  38. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_definition.rb +99 -0
  39. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_definitions.rb +94 -0
  40. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_values.rb +91 -0
  41. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_pipeline_workflows.rb +108 -0
  42. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_project_branches.rb +105 -0
  43. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_project_config.rb +104 -0
  44. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_project_workflow_metrics.rb +121 -0
  45. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_trigger.rb +99 -0
  46. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_user_info.rb +83 -0
  47. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow.rb +121 -0
  48. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_insights.rb +157 -0
  49. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_job_metrics.rb +123 -0
  50. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_jobs.rb +109 -0
  51. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_runs.rb +129 -0
  52. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_summary.rb +118 -0
  53. data/lib/fastlane/plugin/circle_ci/actions/circleci_get_workflow_test_metrics.rb +115 -0
  54. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_all_pipelines.rb +94 -0
  55. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_contexts.rb +132 -0
  56. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_pipeline_definition_triggers.rb +101 -0
  57. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_pipeline_schedules.rb +99 -0
  58. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_projects.rb +89 -0
  59. data/lib/fastlane/plugin/circle_ci/actions/circleci_list_webhooks.rb +111 -0
  60. data/lib/fastlane/plugin/circle_ci/actions/circleci_rerun_workflow.rb +101 -0
  61. data/lib/fastlane/plugin/circle_ci/actions/circleci_set_env_var.rb +102 -0
  62. data/lib/fastlane/plugin/circle_ci/actions/circleci_trigger_pipeline.rb +130 -0
  63. data/lib/fastlane/plugin/circle_ci/actions/circleci_update_pipeline_definition.rb +127 -0
  64. data/lib/fastlane/plugin/circle_ci/actions/circleci_update_pipeline_schedule.rb +134 -0
  65. data/lib/fastlane/plugin/circle_ci/actions/circleci_update_trigger.rb +114 -0
  66. data/lib/fastlane/plugin/circle_ci/actions/circleci_wait_for_pipeline.rb +152 -0
  67. data/lib/fastlane/plugin/circle_ci/helper/circle_ci_helper.rb +102 -1
  68. data/lib/fastlane/plugin/circle_ci/version.rb +1 -1
  69. metadata +99 -7
@@ -0,0 +1,400 @@
1
+ require 'fastlane/action'
2
+ require 'fileutils'
3
+ require_relative '../helper/circle_ci_helper'
4
+
5
+ module Fastlane
6
+ module Actions
7
+ module SharedValues
8
+ CIRCLECI_DOWNLOADED_ARTIFACTS = :CIRCLECI_DOWNLOADED_ARTIFACTS
9
+ end
10
+
11
+ class CircleciDownloadWorkflowArtifactsAction < Action
12
+ def self.run(params)
13
+ UI.message("Downloading artifacts from CircleCI workflow...")
14
+
15
+ # Extract parameters
16
+ api_token, project_slug, branch, workflow_name, job_name, destination_dir, file_extensions = extract_params(params)
17
+
18
+ # Create destination directory if it doesn't exist
19
+ FileUtils.mkdir_p(destination_dir)
20
+
21
+ # Find the target pipeline and workflow
22
+ target_pipeline, target_workflow = find_target_pipeline_and_workflow(api_token, project_slug, branch, workflow_name)
23
+
24
+ # Get the jobs for the workflow and download artifacts
25
+ downloaded_artifacts, total_artifacts = download_job_artifacts(
26
+ api_token,
27
+ project_slug,
28
+ target_workflow,
29
+ workflow_name,
30
+ destination_dir,
31
+ file_extensions,
32
+ job_name
33
+ )
34
+
35
+ # Store values in lane context
36
+ Actions.lane_context[SharedValues::CIRCLECI_DOWNLOADED_ARTIFACTS] = downloaded_artifacts
37
+
38
+ # Prepare and return the result
39
+ result = prepare_result(
40
+ target_workflow,
41
+ workflow_name,
42
+ target_pipeline,
43
+ branch,
44
+ total_artifacts,
45
+ downloaded_artifacts,
46
+ destination_dir
47
+ )
48
+
49
+ UI.success("Downloaded #{total_artifacts} artifacts from the '#{workflow_name}' workflow on #{branch} branch to #{destination_dir}")
50
+
51
+ return result
52
+ end
53
+
54
+ def self.extract_params(params)
55
+ [
56
+ params[:api_token],
57
+ params[:project_slug],
58
+ params[:branch],
59
+ params[:workflow_name],
60
+ params[:job_name],
61
+ params[:destination_dir],
62
+ params[:file_extensions]
63
+ ]
64
+ end
65
+
66
+ def self.find_target_pipeline_and_workflow(api_token, project_slug, branch, workflow_name)
67
+ UI.important("Looking for the latest pipeline on #{branch} branch...")
68
+
69
+ # Get recent pipelines for the project
70
+ pipelines = Helper::CircleCiHelper.get_v2("project/#{project_slug}/pipeline", api_token)
71
+
72
+ # Find the latest pipeline for the specified branch
73
+ target_pipeline = nil
74
+ target_workflow = nil
75
+
76
+ # Continue searching for pipelines until we find one with the target workflow
77
+ pipeline_page = 1
78
+ max_pages_to_search = 10 # Limit how far back we search to avoid excessive API calls
79
+
80
+ while target_workflow.nil? && pipeline_page <= max_pages_to_search
81
+ if pipeline_page > 1
82
+ UI.important("Workflow '#{workflow_name}' not found in recent pipelines. Checking older pipelines (page #{pipeline_page})...")
83
+ # Get older pipelines with pagination
84
+ pipelines = Helper::CircleCiHelper.get_v2("project/#{project_slug}/pipeline", api_token, { page: pipeline_page })
85
+ end
86
+
87
+ # Check each pipeline on this page for the target branch and workflow
88
+ pipelines["items"].each do |pipeline|
89
+ next unless pipeline["vcs"] && pipeline["vcs"]["branch"] == branch
90
+
91
+ UI.message("Checking pipeline ##{pipeline['number']} on #{branch} branch...")
92
+
93
+ # Get the workflows for this pipeline
94
+ workflows = Helper::CircleCiHelper.get_v2("pipeline/#{pipeline["id"]}/workflow", api_token)
95
+
96
+ # Find the target workflow with status "success"
97
+ workflow = workflows["items"].find { |w| w["name"] == workflow_name && w["status"] == "success" }
98
+
99
+ if workflow
100
+ target_pipeline = pipeline
101
+ target_workflow = workflow
102
+ UI.success("Found #{workflow_name} workflow with status 'success' in pipeline ##{pipeline["number"]}")
103
+ break
104
+ end
105
+ end
106
+
107
+ pipeline_page += 1
108
+ end
109
+
110
+ if target_pipeline.nil?
111
+ UI.user_error!("No pipeline found for #{branch} branch")
112
+ end
113
+
114
+ if target_workflow.nil?
115
+ UI.user_error!("No successful '#{workflow_name}' workflow found in any recent pipelines for #{branch} branch")
116
+ else
117
+ UI.success("Using #{workflow_name} workflow: #{target_workflow["id"]} from pipeline ##{target_pipeline["number"]}")
118
+ end
119
+
120
+ return [target_pipeline, target_workflow]
121
+ end
122
+
123
+ def self.download_job_artifacts(api_token, project_slug, target_workflow, workflow_name, destination_dir, file_extensions = nil, job_name = nil)
124
+ # Get the jobs for the workflow
125
+ jobs_result = Helper::CircleCiHelper.get_v2("workflow/#{target_workflow["id"]}/job", api_token)
126
+ jobs = jobs_result["items"]
127
+
128
+ UI.important("Found #{jobs.count} jobs in the #{workflow_name} workflow")
129
+
130
+ # Filter jobs by name if specified
131
+ if job_name
132
+ jobs = jobs.select { |job| job["name"] == job_name }
133
+ if jobs.empty?
134
+ UI.user_error!("No job found with name '#{job_name}' in the #{workflow_name} workflow")
135
+ end
136
+ UI.important("Filtering to only download artifacts from job: #{job_name}")
137
+ end
138
+
139
+ # Download artifacts for each job
140
+ downloaded_artifacts = []
141
+ total_artifacts = 0
142
+
143
+ jobs.each do |job|
144
+ job_artifacts = download_artifacts_for_job(api_token, project_slug, job, destination_dir, file_extensions)
145
+
146
+ if !job_artifacts.empty?
147
+ downloaded_artifacts << {
148
+ job_name: job["name"],
149
+ job_number: job["job_number"],
150
+ artifacts: job_artifacts
151
+ }
152
+ total_artifacts += job_artifacts.count
153
+ end
154
+ end
155
+
156
+ return [downloaded_artifacts, total_artifacts]
157
+ end
158
+
159
+ def self.download_artifacts_for_job(api_token, project_slug, job, destination_dir, file_extensions = nil)
160
+ UI.message("Getting artifacts for job: #{job["name"]}")
161
+
162
+ # Skip jobs with no number (haven't run yet)
163
+ return [] unless job["job_number"]
164
+
165
+ # Get artifacts for this job
166
+ artifacts_result = Helper::CircleCiHelper.get_v2("project/#{project_slug}/#{job["job_number"]}/artifacts", api_token)
167
+ artifacts = artifacts_result["items"]
168
+
169
+ if artifacts.empty?
170
+ UI.message("No artifacts found for job: #{job["name"]}")
171
+ return []
172
+ end
173
+
174
+ # Filter artifacts by extension if specified
175
+ if file_extensions
176
+ extensions = file_extensions.is_a?(Array) ? file_extensions : [file_extensions.to_s]
177
+ filtered_artifacts = filter_artifacts_by_extension(artifacts, extensions)
178
+
179
+ if filtered_artifacts.empty?
180
+ UI.message("No artifacts with extensions #{extensions.join(', ')} found for job: #{job["name"]}")
181
+ return []
182
+ end
183
+
184
+ UI.success("Found #{filtered_artifacts.count} artifacts with extensions #{extensions.join(', ')} for job: #{job["name"]}")
185
+ artifacts = filtered_artifacts
186
+ else
187
+ UI.success("Found #{artifacts.count} artifacts for job: #{job["name"]}")
188
+ end
189
+
190
+ # Download each artifact
191
+ download_artifacts(api_token, job["name"], artifacts, destination_dir)
192
+ end
193
+
194
+ def self.filter_artifacts_by_extension(artifacts, extensions)
195
+ artifacts.select do |artifact|
196
+ # Get the file extension from the path
197
+ ext = File.extname(artifact["path"]).delete('.')
198
+ extensions.include?(ext.downcase)
199
+ end
200
+ end
201
+
202
+ def self.download_artifacts(api_token, job_name, artifacts, destination_dir)
203
+ job_artifacts = []
204
+
205
+ artifacts.each do |artifact|
206
+ download_path = prepare_download_path(destination_dir, job_name, artifact)
207
+
208
+ if download_artifact(api_token, artifact, download_path)
209
+ job_artifacts << {
210
+ job_name: job_name,
211
+ artifact_path: artifact["path"],
212
+ url: artifact["url"],
213
+ download_path: download_path
214
+ }
215
+ end
216
+ end
217
+
218
+ return job_artifacts
219
+ end
220
+
221
+ def self.prepare_download_path(destination_dir, job_name, artifact)
222
+ job_dir = File.join(destination_dir, job_name)
223
+ FileUtils.mkdir_p(job_dir)
224
+
225
+ artifact_filename = File.basename(artifact["path"])
226
+ File.join(job_dir, artifact_filename)
227
+ end
228
+
229
+ def self.download_artifact(api_token, artifact, download_path)
230
+ UI.message("Downloading artifact: #{artifact["path"]} to #{download_path}")
231
+
232
+ # Configure Faraday
233
+ conn = Faraday.new do |f|
234
+ f.headers['Circle-Token'] = api_token if api_token
235
+ f.response :follow_redirects
236
+ f.adapter Faraday.default_adapter
237
+ end
238
+
239
+ # Download the file
240
+ begin
241
+ response = conn.get(artifact["url"])
242
+
243
+ if response.status >= 200 && response.status < 300
244
+ # Write the response body to the destination file
245
+ File.open(download_path, "wb") do |file|
246
+ file.write(response.body)
247
+ end
248
+ UI.success("Successfully downloaded artifact to #{download_path}")
249
+ return true
250
+ else
251
+ UI.error("Failed to download artifact: HTTP #{response.status}")
252
+ return false
253
+ end
254
+ rescue => e
255
+ UI.error("Error downloading artifact: #{e.message}")
256
+ return false
257
+ end
258
+ end
259
+
260
+ def self.prepare_result(target_workflow, workflow_name, target_pipeline, branch, total_artifacts, downloaded_artifacts, destination_dir)
261
+ {
262
+ workflow_id: target_workflow["id"],
263
+ workflow_name: workflow_name,
264
+ pipeline_number: target_pipeline["number"],
265
+ pipeline_id: target_pipeline["id"],
266
+ branch: branch,
267
+ total_artifacts: total_artifacts,
268
+ downloaded_artifacts: downloaded_artifacts,
269
+ destination_dir: destination_dir
270
+ }
271
+ end
272
+
273
+ def self.description
274
+ "Downloads artifacts from a specific CircleCI workflow"
275
+ end
276
+
277
+ def self.details
278
+ "This action downloads all artifacts from a specific CircleCI workflow. By default, it targets the most recent 'test' workflow from the master branch, but you can customize all parameters. Artifacts are downloaded to the specified directory, organized by job name."
279
+ end
280
+
281
+ def self.available_options
282
+ [
283
+ FastlaneCore::ConfigItem.new(key: :api_token,
284
+ env_name: "CIRCLE_CI_API_TOKEN",
285
+ description: "API Token for CircleCI API",
286
+ sensitive: true,
287
+ code_gen_sensitive: true,
288
+ is_string: true,
289
+ default_value: ENV["CIRCLE_CI_API_TOKEN"],
290
+ default_value_dynamic: true,
291
+ optional: false),
292
+ FastlaneCore::ConfigItem.new(key: :project_slug,
293
+ env_name: "CIRCLE_CI_PROJECT_SLUG",
294
+ description: "Project slug in the form of :vcs-type/:org-name/:project-name (e.g. github/myorg/myrepo)",
295
+ is_string: true,
296
+ default_value: ENV["CIRCLE_CI_PROJECT_SLUG"],
297
+ default_value_dynamic: true,
298
+ optional: false),
299
+ FastlaneCore::ConfigItem.new(key: :branch,
300
+ env_name: "CIRCLE_CI_BRANCH",
301
+ description: "The name of the branch to search for workflows",
302
+ is_string: true,
303
+ default_value: "master",
304
+ optional: true),
305
+ FastlaneCore::ConfigItem.new(key: :workflow_name,
306
+ env_name: "CIRCLE_CI_WORKFLOW_NAME",
307
+ description: "The name of the workflow to download artifacts from",
308
+ is_string: true,
309
+ default_value: "test",
310
+ optional: true),
311
+ FastlaneCore::ConfigItem.new(key: :job_name,
312
+ env_name: "CIRCLE_CI_JOB_NAME",
313
+ description: "The name of a specific job to download artifacts from (if not provided, artifacts from all jobs will be downloaded)",
314
+ is_string: true,
315
+ optional: true),
316
+ FastlaneCore::ConfigItem.new(key: :destination_dir,
317
+ env_name: "CIRCLE_CI_ARTIFACT_DESTINATION_DIR",
318
+ description: "Directory where artifacts should be saved",
319
+ is_string: true,
320
+ default_value: "./artifacts",
321
+ optional: true),
322
+ FastlaneCore::ConfigItem.new(key: :file_extensions,
323
+ env_name: "CIRCLE_CI_ARTIFACT_FILE_EXTENSIONS",
324
+ description: "File extensions to download (e.g. 'json' or ['json', 'xml']). If provided, only files with these extensions will be downloaded",
325
+ is_string: false,
326
+ default_value: "json",
327
+ optional: true)
328
+ ]
329
+ end
330
+
331
+ def self.output
332
+ [
333
+ ['CIRCLECI_DOWNLOADED_ARTIFACTS', 'An array of downloaded artifacts information grouped by job']
334
+ ]
335
+ end
336
+
337
+ def self.return_value
338
+ "Returns a hash containing information about the download process, including workflow ID, pipeline details, branch, and downloaded artifacts."
339
+ end
340
+
341
+ def self.authors
342
+ ["crazymanish"]
343
+ end
344
+
345
+ def self.example_code
346
+ [
347
+ '# Download only JSON files (default)
348
+ circleci_download_workflow_artifacts(
349
+ project_slug: "github/myorg/myrepo"
350
+ )',
351
+ '# Download only XML files
352
+ circleci_download_workflow_artifacts(
353
+ project_slug: "github/myorg/myrepo",
354
+ file_extensions: "xml"
355
+ )',
356
+ '# Download both JSON and XML files
357
+ circleci_download_workflow_artifacts(
358
+ project_slug: "github/myorg/myrepo",
359
+ file_extensions: ["json", "xml"]
360
+ )',
361
+ '# Download artifacts from a specific job only
362
+ circleci_download_workflow_artifacts(
363
+ project_slug: "github/myorg/myrepo",
364
+ job_name: "build"
365
+ )',
366
+ 'circleci_download_workflow_artifacts(
367
+ project_slug: "github/myorg/myrepo"
368
+ )',
369
+ 'artifacts_info = circleci_download_workflow_artifacts(
370
+ project_slug: "github/myorg/myrepo",
371
+ branch: "feature/my-branch",
372
+ workflow_name: "integration",
373
+ destination_dir: "./my-artifacts"
374
+ )
375
+
376
+ # Print summary of downloaded artifacts
377
+ UI.message("Downloaded #{artifacts_info[:total_artifacts]} artifacts from #{artifacts_info[:workflow_name]} workflow")
378
+
379
+ # Process downloaded artifacts
380
+ artifacts_info[:downloaded_artifacts].each do |job_artifacts|
381
+ job_name = job_artifacts[:job_name]
382
+ job_artifacts[:artifacts].each do |artifact|
383
+ path = artifact[:download_path]
384
+ # Process artifact files as needed
385
+ puts "Processing #{path} from job #{job_name}"
386
+ end
387
+ end'
388
+ ]
389
+ end
390
+
391
+ def self.is_supported?(platform)
392
+ true
393
+ end
394
+
395
+ def self.category
396
+ :ci
397
+ end
398
+ end
399
+ end
400
+ end
@@ -0,0 +1,101 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/circle_ci_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ CIRCLECI_CHECKOUT_KEY_INFO = :CIRCLECI_CHECKOUT_KEY_INFO
8
+ end
9
+
10
+ class CircleciGetCheckoutKeyAction < Action
11
+ def self.run(params)
12
+ UI.message("Getting CircleCI project checkout key via API v2...")
13
+
14
+ api_token = params[:api_token]
15
+ project_slug = params[:project_slug]
16
+ fingerprint = params[:fingerprint]
17
+
18
+ # Make API request
19
+ result = Helper::CircleCiHelper.get_v2("project/#{project_slug}/checkout-key/#{fingerprint}", api_token)
20
+
21
+ # Store values in lane context
22
+ Actions.lane_context[SharedValues::CIRCLECI_CHECKOUT_KEY_INFO] = result
23
+
24
+ UI.success("Successfully retrieved checkout key with fingerprint #{fingerprint} for project #{project_slug}")
25
+
26
+ return result
27
+ end
28
+
29
+ def self.description
30
+ "Gets a specific checkout key for a CircleCI project using API v2"
31
+ end
32
+
33
+ def self.details
34
+ "This action retrieves details for a specific checkout key for a CircleCI project using the CircleCI API v2. You need to provide the fingerprint of the key you want to retrieve."
35
+ end
36
+
37
+ def self.available_options
38
+ [
39
+ FastlaneCore::ConfigItem.new(key: :api_token,
40
+ env_name: "CIRCLE_CI_API_TOKEN",
41
+ description: "API Token for CircleCI API",
42
+ sensitive: true,
43
+ code_gen_sensitive: true,
44
+ is_string: true,
45
+ default_value: ENV["CIRCLE_CI_API_TOKEN"],
46
+ default_value_dynamic: true,
47
+ optional: false),
48
+ FastlaneCore::ConfigItem.new(key: :project_slug,
49
+ env_name: "CIRCLE_CI_PROJECT_SLUG",
50
+ description: "Project slug in the form of :vcs-type/:org-name/:project-name (e.g. github/myorg/myrepo)",
51
+ is_string: true,
52
+ default_value: ENV["CIRCLE_CI_PROJECT_SLUG"],
53
+ default_value_dynamic: true,
54
+ optional: false),
55
+ FastlaneCore::ConfigItem.new(key: :fingerprint,
56
+ description: "The fingerprint of the checkout key to retrieve",
57
+ is_string: true,
58
+ optional: false)
59
+ ]
60
+ end
61
+
62
+ def self.output
63
+ [
64
+ ['CIRCLECI_CHECKOUT_KEY_INFO', 'A hash containing the checkout key information']
65
+ ]
66
+ end
67
+
68
+ def self.return_value
69
+ "Returns a hash containing the checkout key information including type, fingerprint, and preferred status."
70
+ end
71
+
72
+ def self.authors
73
+ ["crazymanish", "copilot"]
74
+ end
75
+
76
+ def self.example_code
77
+ [
78
+ 'circleci_get_checkout_key(
79
+ project_slug: "gh/MyOrg/my-project",
80
+ fingerprint: "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f"
81
+ )',
82
+ 'key_info = circleci_get_checkout_key(
83
+ project_slug: "gh/MyOrg/my-project",
84
+ fingerprint: "c9:0b:1c:4f:d5:65:56:b9:ad:88:f9:81:2b:37:74:2f"
85
+ )
86
+
87
+ # Use the key information
88
+ UI.message("Key type: #{key_info["type"]}, Public key: #{key_info["public_key"]}")'
89
+ ]
90
+ end
91
+
92
+ def self.is_supported?(platform)
93
+ true
94
+ end
95
+
96
+ def self.category
97
+ :ci
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,96 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/circle_ci_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ CIRCLECI_CHECKOUT_KEYS = :CIRCLECI_CHECKOUT_KEYS
8
+ end
9
+
10
+ class CircleciGetCheckoutKeysAction < Action
11
+ def self.run(params)
12
+ UI.message("Getting CircleCI project checkout keys via API v2...")
13
+
14
+ api_token = params[:api_token]
15
+ project_slug = params[:project_slug]
16
+
17
+ # Make API request
18
+ result = Helper::CircleCiHelper.get_v2("project/#{project_slug}/checkout-key", api_token)
19
+
20
+ # Store values in lane context
21
+ Actions.lane_context[SharedValues::CIRCLECI_CHECKOUT_KEYS] = result
22
+
23
+ UI.success("Successfully retrieved checkout keys for project #{project_slug}")
24
+
25
+ return result
26
+ end
27
+
28
+ def self.description
29
+ "Gets all checkout keys for a CircleCI project using API v2"
30
+ end
31
+
32
+ def self.details
33
+ "This action retrieves all checkout keys for a specific CircleCI project using the CircleCI API v2. Checkout keys are used to check out code from your version control system."
34
+ end
35
+
36
+ def self.available_options
37
+ [
38
+ FastlaneCore::ConfigItem.new(key: :api_token,
39
+ env_name: "CIRCLE_CI_API_TOKEN",
40
+ description: "API Token for CircleCI API",
41
+ sensitive: true,
42
+ code_gen_sensitive: true,
43
+ is_string: true,
44
+ default_value: ENV["CIRCLE_CI_API_TOKEN"],
45
+ default_value_dynamic: true,
46
+ optional: false),
47
+ FastlaneCore::ConfigItem.new(key: :project_slug,
48
+ env_name: "CIRCLE_CI_PROJECT_SLUG",
49
+ description: "Project slug in the form of :vcs-type/:org-name/:project-name (e.g. github/myorg/myrepo)",
50
+ is_string: true,
51
+ default_value: ENV["CIRCLE_CI_PROJECT_SLUG"],
52
+ default_value_dynamic: true,
53
+ optional: false)
54
+ ]
55
+ end
56
+
57
+ def self.output
58
+ [
59
+ ['CIRCLECI_CHECKOUT_KEYS', 'A hash containing checkout keys information']
60
+ ]
61
+ end
62
+
63
+ def self.return_value
64
+ "Returns a hash containing checkout keys information including type, fingerprint, and preferred status."
65
+ end
66
+
67
+ def self.authors
68
+ ["crazymanish", "copilot"]
69
+ end
70
+
71
+ def self.example_code
72
+ [
73
+ 'circleci_get_checkout_keys(
74
+ project_slug: "gh/MyOrg/my-project"
75
+ )',
76
+ 'keys = circleci_get_checkout_keys(
77
+ project_slug: "gh/MyOrg/my-project"
78
+ )
79
+
80
+ # Use the checkout keys
81
+ keys["items"].each do |key|
82
+ UI.message("Found key: #{key["type"]} with fingerprint #{key["fingerprint"]}")
83
+ end'
84
+ ]
85
+ end
86
+
87
+ def self.is_supported?(platform)
88
+ true
89
+ end
90
+
91
+ def self.category
92
+ :ci
93
+ end
94
+ end
95
+ end
96
+ end