fastlane-plugin-appscert 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c6ba0d2a6dcb15ac98b613d9dceef4b3efdf962a4306c961fe351b977d42949b
4
+ data.tar.gz: 11dc2aa82f684f6683788812aa50707a18d52113c00ef60acf060062f55adb29
5
+ SHA512:
6
+ metadata.gz: 0a076e34f12001f542fb153201ee902bcf0a59a0422198a124d620918c6c3e221731a68a89bf9d687e27db4e394679f26badbd4f350f3c141cfa2221a2cbb176
7
+ data.tar.gz: 17a2e7cdaa7376e705bc78b546b97c13ce9eda405e1b2b096ef04481106fe26ace10305072ec731ea375a180964a11782b413ef85872a2062c0b30d2bf39cf10
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AppsCert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # fastlane-plugin-appscert
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/fastlane-plugin-appscert.svg)](https://rubygems.org/gems/fastlane-plugin-appscert)
4
+
5
+ Fastlane plugin for [AppsCert](https://appscert.com) — Apple certificate & provisioning profile management.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ gem install fastlane-plugin-appscert
11
+ ```
12
+
13
+ Or add to your `Gemfile`:
14
+
15
+ ```ruby
16
+ gem 'fastlane-plugin-appscert'
17
+ ```
18
+
19
+ ## Actions
20
+
21
+ ### `appscert_sync`
22
+
23
+ Sync (download) all certificates and provisioning profiles from AppsCert.
24
+
25
+ ```ruby
26
+ lane :sync do
27
+ appscert_sync(
28
+ appscert_api_key: "your_key", # or set APPSCERT_API_KEY env
29
+ output_path: "./certs",
30
+ include_profiles: true
31
+ )
32
+ end
33
+ ```
34
+
35
+ ### `appscert_check`
36
+
37
+ Check expiration status. Fails the build if any cert/profile expires within N days.
38
+
39
+ ```ruby
40
+ lane :check do
41
+ appscert_check(
42
+ days_before_expiry: 30,
43
+ fail_on_expiring: true
44
+ )
45
+ end
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ Set `APPSCERT_API_KEY` environment variable or pass `appscert_api_key` parameter.
51
+
52
+ Get your API key at [appscert.com/dashboard/api-keys](https://appscert.com/dashboard/api-keys).
53
+
54
+ ## License
55
+
56
+ MIT
@@ -0,0 +1,75 @@
1
+ require 'date'
2
+
3
+ module Fastlane
4
+ module Actions
5
+ class AppscertCheckAction < Action
6
+ def self.run(params)
7
+ api_key = params[:appscert_api_key] || ENV['APPSCERT_API_KEY']
8
+ UI.user_error!("No AppsCert API key provided.") unless api_key
9
+
10
+ base_url = params[:api_base_url]
11
+ days_threshold = params[:days_before_expiry] || 30
12
+ fail_on_expiring = params[:fail_on_expiring] != false
13
+
14
+ UI.message("🔍 Checking certificate expiration (threshold: #{days_threshold} days)...")
15
+
16
+ certs = Helper::AppscertHelper.fetch_certificates(api_key, base_url: base_url)
17
+ profiles = Helper::AppscertHelper.fetch_profiles(api_key, base_url: base_url)
18
+
19
+ now = Date.today
20
+ expiring = []
21
+ expired = []
22
+
23
+ (certs + profiles).each do |item|
24
+ next unless item['expiresAt'] || item['expires_at']
25
+ expires = Date.parse(item['expiresAt'] || item['expires_at'])
26
+ days_left = (expires - now).to_i
27
+ name = item['name'] || item['id']
28
+
29
+ if days_left < 0
30
+ expired << { name: name, days: days_left }
31
+ UI.error(" ❌ #{name} — EXPIRED #{-days_left} days ago")
32
+ elsif days_left <= days_threshold
33
+ expiring << { name: name, days: days_left }
34
+ UI.important(" ⚠️ #{name} — expires in #{days_left} days")
35
+ else
36
+ UI.success(" ✅ #{name} — #{days_left} days remaining")
37
+ end
38
+ end
39
+
40
+ if expired.any?
41
+ msg = "#{expired.length} expired certificate(s)/profile(s) found!"
42
+ fail_on_expiring ? UI.user_error!(msg) : UI.error(msg)
43
+ elsif expiring.any?
44
+ msg = "#{expiring.length} item(s) expiring within #{days_threshold} days"
45
+ fail_on_expiring ? UI.user_error!(msg) : UI.important(msg)
46
+ else
47
+ UI.success("✅ All certificates and profiles are healthy!")
48
+ end
49
+
50
+ { expired: expired, expiring: expiring }
51
+ end
52
+
53
+ def self.description
54
+ "Check if any AppsCert certificates or profiles are expiring soon"
55
+ end
56
+
57
+ def self.available_options
58
+ [
59
+ FastlaneCore::ConfigItem.new(key: :appscert_api_key, env_name: "APPSCERT_API_KEY", description: "AppsCert API key", optional: true, sensitive: true, type: String),
60
+ FastlaneCore::ConfigItem.new(key: :api_base_url, env_name: "APPSCERT_API_URL", description: "API base URL", optional: true, type: String),
61
+ FastlaneCore::ConfigItem.new(key: :days_before_expiry, description: "Warn if expiring within N days", optional: true, default_value: 30, type: Integer),
62
+ FastlaneCore::ConfigItem.new(key: :fail_on_expiring, description: "Fail the lane if items are expiring", optional: true, default_value: true, is_string: false)
63
+ ]
64
+ end
65
+
66
+ def self.is_supported?(platform)
67
+ [:ios, :mac].include?(platform)
68
+ end
69
+
70
+ def self.category
71
+ :code_signing
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,61 @@
1
+ module Fastlane
2
+ module Actions
3
+ class AppscertSyncAction < Action
4
+ def self.run(params)
5
+ api_key = params[:appscert_api_key] || ENV['APPSCERT_API_KEY']
6
+ UI.user_error!("No AppsCert API key provided. Set appscert_api_key or APPSCERT_API_KEY env var.") unless api_key
7
+
8
+ base_url = params[:api_base_url]
9
+ output_path = params[:output_path] || './appscert'
10
+ FileUtils.mkdir_p(output_path)
11
+
12
+ UI.message("🔄 Syncing certificates from AppsCert...")
13
+ certs = Helper::AppscertHelper.fetch_certificates(api_key, base_url: base_url)
14
+ UI.message("Found #{certs.length} certificates")
15
+
16
+ certs.each do |cert|
17
+ file = File.join(output_path, "#{cert['name'] || cert['id']}.p12")
18
+ Helper::AppscertHelper.download_certificate(api_key, cert['id'], file, base_url: base_url)
19
+ UI.success(" ✅ #{cert['name']} → #{file}")
20
+ end
21
+
22
+ if params[:include_profiles] != false
23
+ UI.message("🔄 Syncing profiles...")
24
+ profiles = Helper::AppscertHelper.fetch_profiles(api_key, base_url: base_url)
25
+ UI.message("Found #{profiles.length} profiles")
26
+
27
+ profiles.each do |profile|
28
+ file = File.join(output_path, "#{profile['name'] || profile['id']}.mobileprovision")
29
+ Helper::AppscertHelper.download_profile(api_key, profile['id'], file, base_url: base_url)
30
+ UI.success(" ✅ #{profile['name']} → #{file}")
31
+ end
32
+ end
33
+
34
+ UI.success("✅ Sync complete!")
35
+ output_path
36
+ end
37
+
38
+ def self.description
39
+ "Sync certificates and provisioning profiles from AppsCert"
40
+ end
41
+
42
+ def self.available_options
43
+ [
44
+ FastlaneCore::ConfigItem.new(key: :appscert_api_key, env_name: "APPSCERT_API_KEY", description: "AppsCert API key", optional: true, sensitive: true, type: String),
45
+ FastlaneCore::ConfigItem.new(key: :api_base_url, env_name: "APPSCERT_API_URL", description: "API base URL (default: https://appscert.com/api)", optional: true, type: String),
46
+ FastlaneCore::ConfigItem.new(key: :output_path, description: "Directory to save downloaded files", optional: true, default_value: "./appscert", type: String),
47
+ FastlaneCore::ConfigItem.new(key: :include_profiles, description: "Also sync provisioning profiles", optional: true, default_value: true, is_string: false),
48
+ FastlaneCore::ConfigItem.new(key: :bundle_id, description: "Filter by bundle ID", optional: true, type: String)
49
+ ]
50
+ end
51
+
52
+ def self.is_supported?(platform)
53
+ [:ios, :mac].include?(platform)
54
+ end
55
+
56
+ def self.category
57
+ :code_signing
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ require 'faraday'
2
+ require 'json'
3
+
4
+ module Fastlane
5
+ module Helper
6
+ class AppscertHelper
7
+ BASE_URL = 'https://appscert.com/api'
8
+
9
+ def self.api_client(api_key, base_url: nil)
10
+ url = base_url || ENV['APPSCERT_API_URL'] || BASE_URL
11
+ Faraday.new(url: url) do |f|
12
+ f.request :retry, max: 2
13
+ f.headers['Authorization'] = "Bearer #{api_key}"
14
+ f.headers['Content-Type'] = 'application/json'
15
+ f.headers['User-Agent'] = 'fastlane-plugin-appscert/1.0.0'
16
+ f.adapter Faraday.default_adapter
17
+ end
18
+ end
19
+
20
+ def self.fetch_certificates(api_key, base_url: nil)
21
+ client = api_client(api_key, base_url: base_url)
22
+ response = client.get('/certificates')
23
+ raise "AppsCert API error: #{response.status}" unless response.status == 200
24
+ JSON.parse(response.body)
25
+ end
26
+
27
+ def self.fetch_profiles(api_key, base_url: nil)
28
+ client = api_client(api_key, base_url: base_url)
29
+ response = client.get('/profiles')
30
+ raise "AppsCert API error: #{response.status}" unless response.status == 200
31
+ JSON.parse(response.body)
32
+ end
33
+
34
+ def self.download_certificate(api_key, cert_id, output_path, base_url: nil)
35
+ client = api_client(api_key, base_url: base_url)
36
+ response = client.get("/certificates/#{cert_id}/download")
37
+ raise "Download failed: #{response.status}" unless response.status == 200
38
+ File.write(output_path, response.body)
39
+ output_path
40
+ end
41
+
42
+ def self.download_profile(api_key, profile_id, output_path, base_url: nil)
43
+ client = api_client(api_key, base_url: base_url)
44
+ response = client.get("/profiles/#{profile_id}/download")
45
+ raise "Download failed: #{response.status}" unless response.status == 200
46
+ File.write(output_path, response.body)
47
+ output_path
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ require 'fastlane/plugin/appscert/actions/appscert_sync'
2
+ require 'fastlane/plugin/appscert/actions/appscert_check'
3
+ require 'fastlane/plugin/appscert/helper/appscert_helper'
4
+
5
+ module Fastlane
6
+ module Appscert
7
+ def self.all_classes
8
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-appscert
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - AppsCert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday-retry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: fastlane
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Sync, check, and manage Apple certificates and provisioning profiles
84
+ via AppsCert API
85
+ email: hello@appscert.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - LICENSE
91
+ - README.md
92
+ - lib/fastlane/plugin/appscert.rb
93
+ - lib/fastlane/plugin/appscert/actions/appscert_check.rb
94
+ - lib/fastlane/plugin/appscert/actions/appscert_sync.rb
95
+ - lib/fastlane/plugin/appscert/helper/appscert_helper.rb
96
+ homepage: https://appscert.com/docs/fastlane
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '2.6'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.4.20
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Fastlane plugin for AppsCert - Apple certificate management
119
+ test_files: []