fastlane-plugin-wp_sparkling_appcast 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f2ea0991c5b1753e0e556684a1b5a5dc556a072b7312d56aed5260b925a29b88
4
+ data.tar.gz: a5dcfa56b1a282e149854a031da102d1323e2682ff768a29d45c6414179b96ee
5
+ SHA512:
6
+ metadata.gz: 3ece727a2d06c7373c22528b2e631e3040eba8a1886bf2f5b98a807ff32b198ed0a241fd8bf36ac60018793383db17356459eb13d54c88e3f89efccf664408b6
7
+ data.tar.gz: f0c346e6133e39462c01844e0822863142f398e02ad38d9fa8bf3542cded3a2f740308487c7366831f8f271f0d682c5c22cc08bd2fdc31915db0f2f39b00ad95
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 Usiel Riedl <usiel.riedl@automattic.com>
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,70 @@
1
+ # wp_sparkling_appcast plugin
2
+
3
+ This fastlane plugin helps you distribute your macOS app updates using [WordPress's Sparkling Appcast plugin](https://github.com/Usiel/sparkling-appcast). It automates the process of uploading your app's zip file and creating the necessary entries for Sparkle's appcast.xml feed.
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-wp_sparkling_appcast`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin wp_sparkling_appcast
11
+ ```
12
+
13
+ ### Requirements
14
+
15
+ - WordPress installation with the [Sparkling Appcast plugin](https://github.com/Usiel/sparkling-appcast)
16
+ - WordPress Application Password for authentication
17
+ - macOS app packaged as a zip file
18
+ - Sparkle framework integration in your app
19
+
20
+ ## Example
21
+
22
+ Here's how to use this plugin in your Fastfile:
23
+
24
+ ```ruby
25
+ lane :release do
26
+ # First, create your app archive and zip it
27
+ gym(
28
+ scheme: "YourApp",
29
+ export_method: "developer-id",
30
+ output_directory: "build",
31
+ output_name: "YourApp.zip"
32
+ )
33
+
34
+ # Upload to WordPress and create appcast entry
35
+ wp_sparkling_appcast_upload(
36
+ base_url: "https://your-wordpress-site.com",
37
+ wp_user: "your-username",
38
+ wp_application_pw: ENV["WP_APP_PASSWORD"],
39
+ changelog: "## Changes\n- Fixed some bugs\n- Added new features",
40
+ zip_file: "build/YourApp.zip",
41
+ track: 123
42
+ )
43
+ end
44
+ ```
45
+
46
+ ### Parameters
47
+
48
+ | Key | Description | Type | Required | Default |
49
+ | ------------------ | ------------------------------------------------- | ------- | -------- | ----------------------------------- |
50
+ | base_url | Base URL of your WordPress installation | String | Yes | - |
51
+ | wp_user | WordPress username for authentication | String | Yes | - |
52
+ | wp_application_pw | WordPress application password for authentication | String | Yes | - |
53
+ | build_version | Version number of the build (e.g. 1.2.3) | String | No | App bundle's build version |
54
+ | build_number | Build number | Integer | No | App bundle's build number |
55
+ | min_system_version | Minimum system version required | String | No | App bundle's minimum system version |
56
+ | changelog | Changelog for this version | String | No | "" |
57
+ | zip_file | Path to the zip file to upload | String | Yes | - |
58
+ | track | Track ID for this build | Integer | Yes | - |
59
+
60
+ ## Issues and Feedback
61
+
62
+ You are welcome to submit issues with feedback, feature requests, and bugs to this repository.
63
+
64
+ ## Using _fastlane_ Plugins
65
+
66
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
67
+
68
+ ## About _fastlane_
69
+
70
+ _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
@@ -0,0 +1,152 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/wp_sparkling_appcast_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class WpSparklingAppcastUploadAction < Action
7
+
8
+ def self.run(params)
9
+ UI.message("Starting upload to WordPress Sparkling Appcast...")
10
+
11
+ # Extract info from zip if parameters not provided
12
+ if !params[:build_version] || !params[:build_number] || !params[:min_system_version]
13
+ app_info = Helper::WpSparklingAppcastHelper.extract_app_info(params[:zip_file])
14
+
15
+ if app_info
16
+ params[:build_version] ||= app_info[:build_version]
17
+ params[:build_number] ||= app_info[:build_number]
18
+ params[:min_system_version] ||= app_info[:min_system_version]
19
+
20
+ UI.success("Extracted from app bundle: v#{params[:build_version]} (#{params[:build_number]}) - min macOS #{params[:min_system_version]}")
21
+ end
22
+ end
23
+
24
+ attachment_id = Helper::WpSparklingAppcastHelper.upload_zip(params)
25
+ build_id = Helper::WpSparklingAppcastHelper.create_build_entry(params, attachment_id)
26
+
27
+ return {
28
+ attachment_id: attachment_id,
29
+ build_id: build_id
30
+ }
31
+ end
32
+
33
+ def self.description
34
+ "This plugin helps you distribute your builds using WordPress's Sparkling Appcast plugin (Sparkle appcast.xml)"
35
+ end
36
+
37
+ def self.authors
38
+ ["Usiel Riedl"]
39
+ end
40
+
41
+ def self.return_value
42
+ "Returns a hash containing the attachment_id and build_id of the created resources"
43
+ end
44
+
45
+ def self.details
46
+ "This plugin integrates with WordPress's Sparkling Appcast plugin to create Sparkle appcast.xml feeds for macOS app updates. " \
47
+ "It handles uploading your app's zip file and creating the necessary build entries in WordPress. " \
48
+ "Requirements:\n" \
49
+ "- A WordPress installation with the Sparkling Appcast plugin\n" \
50
+ "- WordPress Application Passwords for authentication\n" \
51
+ "- A zip file containing your app update"
52
+ end
53
+
54
+ def self.example_code
55
+ [
56
+ 'wp_sparkling_appcast_upload(
57
+ base_url: "https://your-wordpress-site.com",
58
+ wp_user: "your-username",
59
+ wp_application_pw: ENV["WP_APP_PASSWORD"],
60
+ changelog: "## Changes\n- Fixed some bugs\n- Added new features",
61
+ zip_file: "path/to/YourApp.zip",
62
+ track: 1
63
+ )'
64
+ ]
65
+ end
66
+
67
+ def self.category
68
+ :beta
69
+ end
70
+
71
+ def self.available_options
72
+ [
73
+ FastlaneCore::ConfigItem.new(
74
+ key: :base_url,
75
+ env_name: "WP_SPARKLING_APPCAST_BASE_URL",
76
+ description: "Base URL of your WordPress installation",
77
+ type: String,
78
+ optional: false,
79
+ verify_block: proc do |value|
80
+ UI.user_error!("Invalid URL format for base_url") unless Helper::WpSparklingAppcastHelper.verify_url(value)
81
+ end
82
+ ),
83
+ FastlaneCore::ConfigItem.new(
84
+ key: :wp_user,
85
+ env_name: "WP_SPARKLING_APPCAST_USER",
86
+ description: "WordPress username for authentication",
87
+ type: String,
88
+ optional: false
89
+ ),
90
+ FastlaneCore::ConfigItem.new(
91
+ key: :wp_application_pw,
92
+ env_name: "WP_SPARKLING_APPCAST_APPLICATION_PW",
93
+ description: "WordPress application password for authentication",
94
+ type: String,
95
+ optional: false,
96
+ sensitive: true
97
+ ),
98
+ FastlaneCore::ConfigItem.new(
99
+ key: :build_version,
100
+ env_name: "WP_SPARKLING_APPCAST_BUILD_VERSION",
101
+ description: "Version number of the build (e.g. 1.2.3). Will be extracted from app bundle if not provided",
102
+ type: String,
103
+ optional: true
104
+ ),
105
+ FastlaneCore::ConfigItem.new(
106
+ key: :build_number,
107
+ env_name: "WP_SPARKLING_APPCAST_BUILD_NUMBER",
108
+ description: "Build number. Will be extracted from app bundle if not provided",
109
+ type: Integer,
110
+ optional: true
111
+ ),
112
+ FastlaneCore::ConfigItem.new(
113
+ key: :min_system_version,
114
+ env_name: "WP_SPARKLING_APPCAST_MIN_SYSTEM_VERSION",
115
+ description: "Minimum system version required. Will be extracted from app bundle if not provided",
116
+ type: String,
117
+ optional: true
118
+ ),
119
+ FastlaneCore::ConfigItem.new(
120
+ key: :changelog,
121
+ env_name: "WP_SPARKLING_APPCAST_CHANGELOG",
122
+ description: "Changelog for this version",
123
+ type: String,
124
+ optional: true,
125
+ default_value: ""
126
+ ),
127
+ FastlaneCore::ConfigItem.new(
128
+ key: :zip_file,
129
+ env_name: "WP_SPARKLING_APPCAST_ZIP_FILE",
130
+ description: "Path to the zip file to upload",
131
+ type: String,
132
+ optional: false,
133
+ verify_block: proc do |value|
134
+ UI.user_error!("Zip file not found at path '#{value}'") unless File.exist?(value)
135
+ end
136
+ ),
137
+ FastlaneCore::ConfigItem.new(
138
+ key: :track,
139
+ env_name: "WP_SPARKLING_APPCAST_TRACK",
140
+ description: "Track ID for this build",
141
+ type: Integer,
142
+ optional: false
143
+ )
144
+ ]
145
+ end
146
+
147
+ def self.is_supported?(platform)
148
+ platform == :mac
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,132 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'json'
5
+ require 'zip'
6
+ require 'plist'
7
+
8
+ module Fastlane
9
+ UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
10
+
11
+ module Helper
12
+ class WpSparklingAppcastHelper
13
+ # class methods that you define here become available in your action
14
+ # as `Helper::WpSparklingAppcastHelper.your_method`
15
+ #
16
+ def self.show_message
17
+ UI.message("Hello from the wp_sparkling_appcast plugin helper!")
18
+ end
19
+
20
+ def self.upload_zip(params)
21
+ zip_uri = URI.parse("#{params[:base_url]}/wp-json/wp/v2/media")
22
+ zip_uri.query = URI.encode_www_form({
23
+ 'status' => 'publish',
24
+ 'title' => "#{File.basename(params[:zip_file], '.*')} #{params[:build_version]} (#{params[:build_number]})"
25
+ })
26
+
27
+ UI.message("Uploading zip file...")
28
+
29
+ zip_request = Net::HTTP::Post.new(zip_uri)
30
+ zip_request.basic_auth(params[:wp_user], params[:wp_application_pw])
31
+ zip_request['Content-Type'] = 'application/zip'
32
+ zip_request['Content-Disposition'] = "attachment; filename=\"#{File.basename(params[:zip_file], '.zip')}-#{params[:build_version]}-#{params[:build_number]}.zip\""
33
+
34
+ zip_data = File.read(params[:zip_file])
35
+ zip_request.body = zip_data
36
+
37
+ response = make_request(zip_uri, zip_request, read_timeout: 300)
38
+ attachment_data = JSON.parse(response.body)
39
+
40
+ UI.success("Successfully uploaded zip file with ID: #{attachment_data['id']}")
41
+ attachment_data['id']
42
+ end
43
+
44
+ def self.create_build_entry(params, attachment_id)
45
+ build_uri = URI.parse("#{params[:base_url]}/wp-json/wp/v2/sappcast_app_build")
46
+
47
+ UI.message("Creating app build entry...")
48
+
49
+ build_request = Net::HTTP::Post.new(build_uri)
50
+ build_request.basic_auth(params[:wp_user], params[:wp_application_pw])
51
+ build_request['Content-Type'] = 'application/json'
52
+
53
+ build_data = {
54
+ meta: {
55
+ sappcast_app_build_version: params[:build_version],
56
+ sappcast_app_build_number: params[:build_number],
57
+ sappcast_app_build_min_system_version: params[:min_system_version],
58
+ sappcast_app_build_attachment_id: attachment_id,
59
+ sappcast_app_build_changelog: params[:changelog]
60
+ },
61
+ sappcast_track: params[:track],
62
+ status: 'draft'
63
+ }
64
+
65
+ build_request.body = build_data.to_json
66
+
67
+ response = make_request(build_uri, build_request)
68
+ build_result = JSON.parse(response.body)
69
+
70
+ UI.success("Successfully created app build entry with ID: #{build_result['id']}")
71
+ build_result['id']
72
+ end
73
+
74
+ def self.verify_url(url)
75
+ uri = URI.parse(url)
76
+ return uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
77
+ rescue URI::InvalidURIError
78
+ return false
79
+ end
80
+
81
+ def self.extract_app_info(zip_file_path)
82
+ UI.message("Extracting app info from zip file...")
83
+
84
+ Zip::File.open(zip_file_path) do |zip_file|
85
+ # Find the .app directory in the zip
86
+ app_entry = zip_file.glob('*.app/Contents/Info.plist').first
87
+
88
+ unless app_entry
89
+ UI.user_error!("No .app bundle found in zip file")
90
+ return nil
91
+ end
92
+
93
+ # Read the plist content
94
+ plist_content = app_entry.get_input_stream.read
95
+ info_plist = Plist.parse_xml(plist_content)
96
+
97
+ {
98
+ build_version: info_plist['CFBundleShortVersionString'],
99
+ build_number: info_plist['CFBundleVersion'].to_i,
100
+ min_system_version: info_plist['LSMinimumSystemVersion']
101
+ }
102
+ end
103
+ rescue => e
104
+ UI.error("Failed to extract app info: #{e.message}")
105
+ nil
106
+ end
107
+
108
+ private
109
+
110
+ def self.make_request(uri, request, read_timeout: 30)
111
+ response = Net::HTTP.start(uri.hostname, uri.port,
112
+ use_ssl: uri.scheme == 'https',
113
+ read_timeout: read_timeout,
114
+ open_timeout: 10
115
+ ) do |http|
116
+ http.request(request)
117
+ end
118
+
119
+ unless response.is_a?(Net::HTTPSuccess)
120
+ error_message = begin
121
+ JSON.parse(response.body)['message']
122
+ rescue
123
+ response.body
124
+ end
125
+ UI.user_error!("Request failed: #{response.code} - #{error_message}")
126
+ end
127
+
128
+ response
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module WpSparklingAppcast
3
+ VERSION = "0.3.0"
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/wp_sparkling_appcast/version'
2
+
3
+ module Fastlane
4
+ module WpSparklingAppcast
5
+ # Return all .rb files inside the "actions" and "helper" directory
6
+ def self.all_classes
7
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
8
+ end
9
+ end
10
+ end
11
+
12
+ # By default we want to import all available actions and helpers
13
+ # A plugin can contain any number of actions and plugins
14
+ Fastlane::WpSparklingAppcast.all_classes.each do |current|
15
+ require current
16
+ end
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-wp_sparkling_appcast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Usiel Riedl
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubyzip
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: plist
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 3.6.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.6.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: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
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
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec_junit_formatter
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: webmock
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email: usiel.riedl@gmail.com
169
+ executables: []
170
+ extensions: []
171
+ extra_rdoc_files: []
172
+ files:
173
+ - LICENSE
174
+ - README.md
175
+ - lib/fastlane/plugin/wp_sparkling_appcast.rb
176
+ - lib/fastlane/plugin/wp_sparkling_appcast/actions/wp_sparkling_appcast_upload_action.rb
177
+ - lib/fastlane/plugin/wp_sparkling_appcast/helper/wp_sparkling_appcast_helper.rb
178
+ - lib/fastlane/plugin/wp_sparkling_appcast/version.rb
179
+ homepage: https://github.com/Usiel/fastlane-plugin-wp_sparkling_appcast
180
+ licenses:
181
+ - MIT
182
+ metadata:
183
+ rubygems_mfa_required: 'true'
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: 2.7.0
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubygems_version: 3.4.10
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: This plugin helps you distribute your builds using WordPress's Sparkling
203
+ Appcast plugin (Sparkle appcast.xml)
204
+ test_files: []