fastlane-plugin-hexsign 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 67ae47604a746cc168dd35f48cc3f58d8eb9d70f9c28613004673ecf22b0491d
4
- data.tar.gz: f20b85fc29619f3a33bed881b02d49f25bd1db91d9f697776910ef37ea8e60a1
3
+ metadata.gz: f17f684819fe3e6e0b9d2d972ad9bff85f302efe7cabba4177d1059d110bfc17
4
+ data.tar.gz: e0060da7f20a7936f19d5b8f9de1b18de8b88d43dd8bcd182a32da4ceff56fac
5
5
  SHA512:
6
- metadata.gz: 56c2e8435a98b6e2e25291eb317bc8eaa4c61cc983264072056d230c8cbad5eba3a17f9d6d089ead9354620da8e2dfba53d80d2b7f6af04a5242873d60c11cde
7
- data.tar.gz: a32eae25d357b1676bcb5b15821e77c3609f5842dd0043d90ad9bc7e9edbe0c7cbdf189257c0366f5a1da381b6bc55d527e9cd36946d9c688498cb1a505f336d
6
+ metadata.gz: e34fa388365f8cb1b649e1cf5d5be8c9aea20e0a769d6db2622266e1ca4a96410aa4c09c792ea4891389b9f87d4f80080ee1505669e0dd5efc48c39077ca4fa4
7
+ data.tar.gz: d0338cac4e02ae2fefc96d54c001fb95b2f1570cffa9def3cf8871db8a459c510c174ef0a536382c8589c3c58caaa5373d0d480b722178688199ebbb568f1773
data/README.md CHANGED
@@ -63,6 +63,7 @@ hexsign_certificates_download(
63
63
  | `id` | `HEXSIGN_CERTIFICATE_ID` | yes | Certificate ID |
64
64
  | `output_dir` | `HEXSIGN_CERTIFICATE_OUTPUT_DIR` | no | Output directory |
65
65
  | `filename` | `HEXSIGN_CERTIFICATE_FILENAME` | no | Base filename (no extension) |
66
+ | `keychain` | `HEXSIGN_KEYCHAIN` | no | macOS only — keychain to create and import the `.p12` into, ready for codesigning |
66
67
 
67
68
  ### `hexsign_profiles_download`
68
69
 
@@ -80,6 +81,53 @@ hexsign_profiles_download(
80
81
  | `id` | `HEXSIGN_PROFILE_ID` | yes | Provisioning profile ID |
81
82
  | `output_dir` | `HEXSIGN_PROFILE_OUTPUT_DIR` | no | Output directory |
82
83
  | `filename` | `HEXSIGN_PROFILE_FILENAME` | no | Filename (no extension) |
84
+ | `install` | `HEXSIGN_PROFILE_INSTALL` | no | macOS only — also install the profile where Xcode finds it |
85
+
86
+ ### `hexsign_certificates_download_by_type`
87
+
88
+ Downloads **every** signing certificate of a given type for one Apple Developer
89
+ team. Survives certificate rotation: no UUID to update when a cert is renewed.
90
+
91
+ Returns an array of `{ p12:, password: }` hashes — one per downloaded certificate.
92
+
93
+ ```ruby
94
+ pairs = hexsign_certificates_download_by_type(
95
+ type: "IOS_DISTRIBUTION",
96
+ team_id: "ABCDE12345",
97
+ output_dir: "build/sign"
98
+ )
99
+ # => [{ p12: "build/sign/foo.p12", password: "build/sign/foo.password" }, ...]
100
+ ```
101
+
102
+ | Option | Env | Required | Description |
103
+ |---|---|---|---|
104
+ | `type` | `HEXSIGN_CERTIFICATE_TYPE` | yes | Apple cert type (e.g. `IOS_DISTRIBUTION`) |
105
+ | `team_id` | `HEXSIGN_TEAM_ID` | yes | Apple Developer team id |
106
+ | `output_dir` | `HEXSIGN_CERTIFICATE_OUTPUT_DIR` | no | Output directory |
107
+ | `keychain` | `HEXSIGN_KEYCHAIN` | no | macOS only — keychain to create and import every downloaded `.p12` into, ready for codesigning |
108
+
109
+ ### `hexsign_profiles_download_by_bundle_id`
110
+
111
+ Downloads **every** provisioning profile for a bundle identifier. Survives
112
+ profile rotation: no UUID to update when a profile is regenerated.
113
+
114
+ Returns an array of absolute paths to the downloaded `.mobileprovision` files.
115
+
116
+ ```ruby
117
+ paths = hexsign_profiles_download_by_bundle_id(
118
+ bundle_id: "com.example.app",
119
+ team_id: "ABCDE12345", # optional — scopes across linked Apple accounts
120
+ output_dir: "build/sign"
121
+ )
122
+ # => ["build/sign/foo.mobileprovision", "build/sign/bar.mobileprovision"]
123
+ ```
124
+
125
+ | Option | Env | Required | Description |
126
+ |---|---|---|---|
127
+ | `bundle_id` | `HEXSIGN_BUNDLE_ID` | yes | App bundle identifier (exact match) |
128
+ | `team_id` | `HEXSIGN_TEAM_ID` | no | Apple Developer team id — scopes across linked accounts |
129
+ | `output_dir` | `HEXSIGN_PROFILE_OUTPUT_DIR` | no | Output directory |
130
+ | `install` | `HEXSIGN_PROFILE_INSTALL` | no | macOS only — also install every downloaded profile where Xcode finds them |
83
131
 
84
132
  ## Example lane
85
133
 
@@ -10,6 +10,7 @@ module Fastlane
10
10
  args = ["certificates", "download", params[:id]]
11
11
  args.push("--output-dir", params[:output_dir]) if params[:output_dir]
12
12
  args.push("--filename", params[:filename]) if params[:filename]
13
+ args.push("--keychain", params[:keychain]) if params[:keychain]
13
14
 
14
15
  Helper::HexsignHelper.run(args).tap { UI.success("Downloaded certificate #{params[:id]}") }
15
16
  end
@@ -54,6 +55,13 @@ module Fastlane
54
55
  description: "Base filename (no extension) for the downloaded files",
55
56
  optional: true,
56
57
  type: String
58
+ ),
59
+ FastlaneCore::ConfigItem.new(
60
+ key: :keychain,
61
+ env_name: "HEXSIGN_KEYCHAIN",
62
+ description: "macOS only: create this keychain and import the downloaded .p12 into it, ready for codesigning",
63
+ optional: true,
64
+ type: String
57
65
  )
58
66
  ]
59
67
  end
@@ -64,7 +72,8 @@ module Fastlane
64
72
 
65
73
  def self.example_code
66
74
  [
67
- 'hexsign_certificates_download(id: "cert-abc123", output_dir: "build/sign")'
75
+ 'hexsign_certificates_download(id: "cert-abc123", output_dir: "build/sign")',
76
+ 'hexsign_certificates_download(id: "cert-abc123", keychain: "/tmp/hexsign-ci.keychain-db")'
68
77
  ]
69
78
  end
70
79
 
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fastlane/action"
4
+ require_relative "../helper/hexsign_helper"
5
+
6
+ module Fastlane
7
+ module Actions
8
+ class HexsignCertificatesDownloadByTypeAction < Action
9
+ def self.run(params)
10
+ args = [
11
+ "certificates", "download",
12
+ "--type", params[:type],
13
+ "--team-id", params[:team_id]
14
+ ]
15
+ args.push("--output-dir", params[:output_dir]) if params[:output_dir]
16
+ args.push("--keychain", params[:keychain]) if params[:keychain]
17
+
18
+ stdout = Helper::HexsignHelper.run(args)
19
+ pairs = parse_stdout(stdout)
20
+
21
+ UI.success("Downloaded #{pairs.size} #{params[:type]} certificate(s) for team #{params[:team_id]}")
22
+ pairs
23
+ end
24
+
25
+ # The CLI prints two lines per certificate: .p12 path then .password path.
26
+ # With --keychain it also prints a trailing "imported N certificate(s)…"
27
+ # summary line, which is dropped by keeping only file-path lines.
28
+ # Returns [{ p12: "...", password: "..." }, ...].
29
+ def self.parse_stdout(stdout)
30
+ lines = stdout.split("\n").map(&:strip).reject(&:empty?)
31
+ lines = lines.select { |line| line.end_with?(".p12", ".password") }
32
+ pairs = []
33
+ lines.each_slice(2) do |p12, password|
34
+ pairs << { p12: p12, password: password }
35
+ end
36
+ pairs
37
+ end
38
+
39
+ def self.description
40
+ "Download every signing certificate of a given type for one Apple Developer team via the HexSign CLI."
41
+ end
42
+
43
+ def self.authors
44
+ ["HexSign"]
45
+ end
46
+
47
+ def self.details
48
+ <<~DETAILS
49
+ Wraps `hexsign certificates download --type <T> --team-id <ID>`. Returns an
50
+ array of { p12:, password: } hashes — one per downloaded certificate.
51
+
52
+ Survives certificate rotation: you point at a cert type (e.g. IOS_DISTRIBUTION)
53
+ rather than a specific UUID that changes when a cert is renewed.
54
+
55
+ The hexsign binary must be on PATH — install via `brew install hexsign` or the
56
+ hexsign/hexsign-cli GitHub Action. Set HEXSIGN_CLIENT_ID and HEXSIGN_CLIENT_SECRET
57
+ so the CLI runs in machine mode.
58
+
59
+ Accepted types: IOS_DEVELOPMENT, IOS_DISTRIBUTION, MAC_APP_DEVELOPMENT,
60
+ MAC_APP_DISTRIBUTION, MAC_INSTALLER_DISTRIBUTION, DEVELOPER_ID_APPLICATION,
61
+ DEVELOPER_ID_APPLICATION_G2, DEVELOPER_ID_KEXT, DEVELOPER_ID_KEXT_G2,
62
+ DEVELOPER_ID_INSTALLER, DEVELOPMENT, DISTRIBUTION, PASS_TYPE_ID,
63
+ PASS_TYPE_ID_WITH_NFC.
64
+ DETAILS
65
+ end
66
+
67
+ def self.available_options
68
+ [
69
+ FastlaneCore::ConfigItem.new(
70
+ key: :type,
71
+ env_name: "HEXSIGN_CERTIFICATE_TYPE",
72
+ description: "Apple certificate type, e.g. IOS_DISTRIBUTION",
73
+ optional: false,
74
+ type: String
75
+ ),
76
+ FastlaneCore::ConfigItem.new(
77
+ key: :team_id,
78
+ env_name: "HEXSIGN_TEAM_ID",
79
+ description: "Apple Developer team identifier to scope the download to",
80
+ optional: false,
81
+ type: String
82
+ ),
83
+ FastlaneCore::ConfigItem.new(
84
+ key: :output_dir,
85
+ env_name: "HEXSIGN_CERTIFICATE_OUTPUT_DIR",
86
+ description: "Directory to write the .p12 and .password files into",
87
+ optional: true,
88
+ type: String
89
+ ),
90
+ FastlaneCore::ConfigItem.new(
91
+ key: :keychain,
92
+ env_name: "HEXSIGN_KEYCHAIN",
93
+ description: "macOS only: create this keychain and import every downloaded .p12 into it, ready for codesigning",
94
+ optional: true,
95
+ type: String
96
+ )
97
+ ]
98
+ end
99
+
100
+ def self.output
101
+ [
102
+ ["HEXSIGN_CERTIFICATES_DOWNLOAD_BY_TYPE_COUNT", "Number of certificates downloaded"]
103
+ ]
104
+ end
105
+
106
+ def self.return_value
107
+ "Array of { p12:, password: } hashes — one per downloaded certificate."
108
+ end
109
+
110
+ def self.is_supported?(platform)
111
+ %i[ios mac tvos watchos visionos].include?(platform)
112
+ end
113
+
114
+ def self.example_code
115
+ [
116
+ 'pairs = hexsign_certificates_download_by_type(
117
+ type: "IOS_DISTRIBUTION",
118
+ team_id: "ABCDE12345",
119
+ output_dir: "build/sign"
120
+ )
121
+ # => [{ p12: "build/sign/foo.p12", password: "build/sign/foo.password" }, ...]'
122
+ ]
123
+ end
124
+
125
+ def self.category
126
+ :code_signing
127
+ end
128
+ end
129
+ end
130
+ end
@@ -10,6 +10,7 @@ module Fastlane
10
10
  args = ["profiles", "download", params[:id]]
11
11
  args.push("--output-dir", params[:output_dir]) if params[:output_dir]
12
12
  args.push("--filename", params[:filename]) if params[:filename]
13
+ args.push("--install") if params[:install]
13
14
 
14
15
  Helper::HexsignHelper.run(args).tap { UI.success("Downloaded provisioning profile #{params[:id]}") }
15
16
  end
@@ -54,6 +55,14 @@ module Fastlane
54
55
  description: "Filename (no extension) for the downloaded profile",
55
56
  optional: true,
56
57
  type: String
58
+ ),
59
+ FastlaneCore::ConfigItem.new(
60
+ key: :install,
61
+ env_name: "HEXSIGN_PROFILE_INSTALL",
62
+ description: "macOS only: also install the profile into ~/Library/MobileDevice/Provisioning Profiles, where Xcode finds it",
63
+ optional: true,
64
+ type: Boolean,
65
+ default_value: false
57
66
  )
58
67
  ]
59
68
  end
@@ -64,7 +73,8 @@ module Fastlane
64
73
 
65
74
  def self.example_code
66
75
  [
67
- 'hexsign_profiles_download(id: "prof-xyz789", output_dir: "build/sign")'
76
+ 'hexsign_profiles_download(id: "prof-xyz789", output_dir: "build/sign")',
77
+ 'hexsign_profiles_download(id: "prof-xyz789", install: true)'
68
78
  ]
69
79
  end
70
80
 
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fastlane/action"
4
+ require_relative "../helper/hexsign_helper"
5
+
6
+ module Fastlane
7
+ module Actions
8
+ class HexsignProfilesDownloadByBundleIdAction < Action
9
+ def self.run(params)
10
+ args = ["profiles", "download", "--bundle-id", params[:bundle_id]]
11
+ args.push("--team-id", params[:team_id]) if params[:team_id]
12
+ args.push("--output-dir", params[:output_dir]) if params[:output_dir]
13
+ args.push("--install") if params[:install]
14
+
15
+ stdout = Helper::HexsignHelper.run(args)
16
+ # With --install the CLI also prints "installed <name> -> <path>" lines;
17
+ # keep only the downloaded-file paths.
18
+ paths = stdout.split("\n").map(&:strip).reject(&:empty?)
19
+ .reject { |line| line.start_with?("installed ") }
20
+
21
+ UI.success("Downloaded #{paths.size} provisioning profile(s) for bundle #{params[:bundle_id]}")
22
+ paths
23
+ end
24
+
25
+ def self.description
26
+ "Download every provisioning profile for a given bundle identifier via the HexSign CLI."
27
+ end
28
+
29
+ def self.authors
30
+ ["HexSign"]
31
+ end
32
+
33
+ def self.details
34
+ <<~DETAILS
35
+ Wraps `hexsign profiles download --bundle-id <ID> [--team-id <TID>]`. Returns an
36
+ array of absolute paths to the downloaded `.mobileprovision` files.
37
+
38
+ Survives profile rotation: you point at a bundle identifier rather than the
39
+ UUID of a specific provisioning profile.
40
+
41
+ Pass `team_id` when the same bundle id exists in more than one linked Apple
42
+ account to avoid pulling profiles from the wrong team.
43
+
44
+ The hexsign binary must be on PATH — install via `brew install hexsign` or the
45
+ hexsign/hexsign-cli GitHub Action. Set HEXSIGN_CLIENT_ID and HEXSIGN_CLIENT_SECRET
46
+ so the CLI runs in machine mode.
47
+ DETAILS
48
+ end
49
+
50
+ def self.available_options
51
+ [
52
+ FastlaneCore::ConfigItem.new(
53
+ key: :bundle_id,
54
+ env_name: "HEXSIGN_BUNDLE_ID",
55
+ description: "App bundle identifier (exact match)",
56
+ optional: false,
57
+ type: String
58
+ ),
59
+ FastlaneCore::ConfigItem.new(
60
+ key: :team_id,
61
+ env_name: "HEXSIGN_TEAM_ID",
62
+ description: "Apple Developer team identifier — scopes the download across linked accounts",
63
+ optional: true,
64
+ type: String
65
+ ),
66
+ FastlaneCore::ConfigItem.new(
67
+ key: :output_dir,
68
+ env_name: "HEXSIGN_PROFILE_OUTPUT_DIR",
69
+ description: "Directory to write the .mobileprovision files into",
70
+ optional: true,
71
+ type: String
72
+ ),
73
+ FastlaneCore::ConfigItem.new(
74
+ key: :install,
75
+ env_name: "HEXSIGN_PROFILE_INSTALL",
76
+ description: "macOS only: also install every downloaded profile into the directory Xcode reads",
77
+ optional: true,
78
+ type: Boolean,
79
+ default_value: false
80
+ )
81
+ ]
82
+ end
83
+
84
+ def self.return_value
85
+ "Array of absolute paths to the downloaded .mobileprovision files."
86
+ end
87
+
88
+ def self.is_supported?(platform)
89
+ %i[ios mac tvos watchos visionos].include?(platform)
90
+ end
91
+
92
+ def self.example_code
93
+ [
94
+ 'paths = hexsign_profiles_download_by_bundle_id(
95
+ bundle_id: "com.example.app",
96
+ team_id: "ABCDE12345",
97
+ output_dir: "build/sign"
98
+ )
99
+ # => ["build/sign/foo.mobileprovision", "build/sign/bar.mobileprovision"]'
100
+ ]
101
+ end
102
+
103
+ def self.category
104
+ :code_signing
105
+ end
106
+ end
107
+ end
108
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Fastlane
4
4
  module Hexsign
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-hexsign
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - HexSign
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-12 00:00:00.000000000 Z
11
+ date: 2026-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastlane
@@ -76,7 +76,9 @@ files:
76
76
  - README.md
77
77
  - lib/fastlane/plugin/hexsign.rb
78
78
  - lib/fastlane/plugin/hexsign/actions/hexsign_certificates_download.rb
79
+ - lib/fastlane/plugin/hexsign/actions/hexsign_certificates_download_by_type.rb
79
80
  - lib/fastlane/plugin/hexsign/actions/hexsign_profiles_download.rb
81
+ - lib/fastlane/plugin/hexsign/actions/hexsign_profiles_download_by_bundle_id.rb
80
82
  - lib/fastlane/plugin/hexsign/helper/hexsign_helper.rb
81
83
  - lib/fastlane/plugin/hexsign/version.rb
82
84
  homepage: https://github.com/hexsign/fastlane-plugin-hexsign