fastlane-plugin-appshot 0.1.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 +7 -0
- data/CHANGELOG.md +14 -0
- data/LICENSE +21 -0
- data/README.md +81 -0
- data/lib/fastlane/plugin/appshot/actions/appshot_action.rb +143 -0
- data/lib/fastlane/plugin/appshot/helper/appshot_helper.rb +119 -0
- data/lib/fastlane/plugin/appshot/version.rb +5 -0
- data/lib/fastlane/plugin/appshot.rb +16 -0
- metadata +49 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a15470692555262a4564076e0e13781454d5ac94f1e0a4127113f4ba163a2689
|
|
4
|
+
data.tar.gz: 96ee3e2203453bec0644b375c40223166232e35dc4241b7fa172a4b9d37090e3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f10805d5c8d3fb8ff640853f268251492740731cf72c9363f8e91c274b341995189d4c9953ae730b82912858e4f2f075bc09d2de2cdc29cdd52c2bc8699b97a5
|
|
7
|
+
data.tar.gz: 7e4fffaadfc59f6d3c9ebb2bf446b4ae3e62b7c68af7145b30e6e1dd5cc89e4409de5b7c9a7e143337dbe81a5f9ae205f23cb3a5f9410c51f5a0e086b70d3508
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to fastlane-plugin-appshot are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-10-08
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- The `appshot` action. For every locale it copies fastlane snapshot's capture of each screen into an [appshot](https://github.com/jems19s/appshot-studio) studio (a capture named `<simulator>-<name>.png` goes to the slot whose screenshot is `<name>.png`), renders the framed, captioned screenshots with appshot, and copies them into `<output_directory>/<locale>/`, the folder deliver uploads.
|
|
10
|
+
- Options `studio`, `app`, `raw_screenshots`, `device`, `locales`, `output_directory`, `appshot_path` and `chrome`, each also settable through an `APPSHOT_*` environment variable.
|
|
11
|
+
- Safeguards: the action refuses to read raw captures from the folder deliver uploads, warns about other PNGs deliver would upload alongside the framed ones, asks for `device:` when captures from several simulators match, and explains how to install appshot when it is missing.
|
|
12
|
+
- Requires Ruby 3.1 or later, like current fastlane.
|
|
13
|
+
|
|
14
|
+
[0.1.0]: https://github.com/jems19s/fastlane-plugin-appshot/releases/tag/v0.1.0
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Maksim Zhelezniakov <48087000+jems19s@users.noreply.github.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,81 @@
|
|
|
1
|
+
# fastlane-plugin-appshot
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/fastlane-plugin-appshot)
|
|
4
|
+
|
|
5
|
+
A [_fastlane_](https://github.com/fastlane/fastlane) action that turns fastlane snapshot's raw captures into finished App Store screenshots with [appshot](https://github.com/jems19s/appshot-studio) — real device bezels, localized captions, generated backgrounds — and puts them where `deliver` uploads from.
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
lane :screenshots do
|
|
9
|
+
capture_screenshots(output_directory: "fastlane/raw_screenshots")
|
|
10
|
+
appshot(raw_screenshots: "fastlane/raw_screenshots")
|
|
11
|
+
upload_to_app_store(skip_binary_upload: true, skip_metadata: true)
|
|
12
|
+
end
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
For every locale the action:
|
|
16
|
+
|
|
17
|
+
1. copies snapshot's capture of each screen into the appshot studio, so every language gets its own app screens;
|
|
18
|
+
2. runs `appshot render`;
|
|
19
|
+
3. copies the framed PNGs into `fastlane/screenshots/<locale>/`, the folder `deliver` uploads.
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
brew install jems19s/tap/appshot
|
|
25
|
+
fastlane add_plugin appshot
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then, once, create the appshot studio next to your `fastlane` folder — the device, captions, colors and layout of your screenshots. Copy one locale's captures into a folder under plain names (`map.png`, `place.png`, …) and run:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
mkdir appshot && cd appshot
|
|
32
|
+
appshot init --name myapp --device "iPhone 17 Pro Max" --screenshots ../plain-captures \
|
|
33
|
+
--locale en-US --locale de-DE \
|
|
34
|
+
--caption 'The best cafés,\n*right around you*' --caption 'Know exactly\n*what to order*'
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Translate the captions in `apps/myapp/captions/<locale>.json`, style it in `apps/myapp/config.json`, and commit the studio (add `devices/` and `output/` to its `.gitignore`). See the [appshot README](https://github.com/jems19s/appshot-studio#readme) for everything you can change, or let a coding agent do it with appshot's [skill](https://github.com/jems19s/appshot-studio#with-a-coding-agent).
|
|
38
|
+
|
|
39
|
+
### How captures are matched
|
|
40
|
+
|
|
41
|
+
fastlane snapshot saves `<simulator name>-<name>.png` in one folder per locale. A capture goes to the slot whose `screenshot` is `<name>.png`, so name your `snapshot("…")` calls after the studio's screenshots:
|
|
42
|
+
|
|
43
|
+
```swift
|
|
44
|
+
snapshot("map") // fastlane/raw_screenshots/de-DE/iPhone 17 Pro Max-map.png → apps/myapp/assets/de-DE/map.png
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If snapshot runs on several simulators, say which one appshot frames with `device: "iPhone 17 Pro Max"`. A locale with no captures keeps the screenshots already in the studio.
|
|
48
|
+
|
|
49
|
+
### Keep raw captures out of deliver's folder
|
|
50
|
+
|
|
51
|
+
snapshot writes to `fastlane/screenshots` by default — the folder `deliver` uploads. Point it somewhere else (`output_directory("./fastlane/raw_screenshots")` in the Snapfile, or the `capture_screenshots` option above), or `deliver` uploads raw and framed images side by side. The action refuses to read and write the same folder, and warns about any other PNGs it finds where it copies.
|
|
52
|
+
|
|
53
|
+
## Options
|
|
54
|
+
|
|
55
|
+
| Key | Default | Description |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| `studio` | `appshot` | appshot studio: the folder holding `apps/`, `templates/` and `devices/` |
|
|
58
|
+
| `app` | the only app | app under `apps/` |
|
|
59
|
+
| `raw_screenshots` | | snapshot's `output_directory`. Leave it out to render the screenshots already in the studio |
|
|
60
|
+
| `device` | | simulator whose captures to use, when `raw_screenshots` holds several |
|
|
61
|
+
| `locales` | all the app's locales | locales to import and render |
|
|
62
|
+
| `output_directory` | `fastlane/screenshots` | framed PNGs go to `<output_directory>/<locale>/` |
|
|
63
|
+
| `appshot_path` | `appshot` | the appshot command |
|
|
64
|
+
| `chrome` | found automatically | Chrome or Chromium to render with |
|
|
65
|
+
|
|
66
|
+
Every option can also come from an environment variable: `APPSHOT_STUDIO`, `APPSHOT_APP`, `APPSHOT_RAW_SCREENSHOTS`, `APPSHOT_DEVICE`, `APPSHOT_LOCALES`, `APPSHOT_OUTPUT_DIRECTORY`, `APPSHOT_PATH`, `APPSHOT_CHROME`.
|
|
67
|
+
|
|
68
|
+
The action returns a hash of locale → paths of the copied screenshots.
|
|
69
|
+
|
|
70
|
+
## Development
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bundle install
|
|
74
|
+
bundle exec rake # tests and rubocop
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The tests use a stand-in for the `appshot` binary, so they run without appshot or Chrome.
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
require "fastlane/action"
|
|
2
|
+
require_relative "../helper/appshot_helper"
|
|
3
|
+
|
|
4
|
+
module Fastlane
|
|
5
|
+
module Actions
|
|
6
|
+
class AppshotAction < Action
|
|
7
|
+
def self.run(params)
|
|
8
|
+
studio = File.expand_path(params[:studio])
|
|
9
|
+
appshot_path = params[:appshot_path]
|
|
10
|
+
UI.message("appshot #{Helper::AppshotHelper.appshot_version(appshot_path)}")
|
|
11
|
+
|
|
12
|
+
app = Helper::AppshotHelper.app_name(studio, params[:app])
|
|
13
|
+
config = Helper::AppshotHelper.load_config(studio, app)
|
|
14
|
+
locales = Helper::AppshotHelper.selected_locales(config, params[:locales])
|
|
15
|
+
slots = config.fetch("slots")
|
|
16
|
+
output_directory = File.expand_path(params[:output_directory])
|
|
17
|
+
|
|
18
|
+
if params[:raw_screenshots]
|
|
19
|
+
raw_screenshots = File.expand_path(params[:raw_screenshots])
|
|
20
|
+
if raw_screenshots == output_directory
|
|
21
|
+
UI.user_error!("raw_screenshots and output_directory are both #{output_directory}: deliver would upload " \
|
|
22
|
+
"the raw captures next to the framed ones. Have snapshot write somewhere else, e.g. " \
|
|
23
|
+
"capture_screenshots(output_directory: \"fastlane/raw_screenshots\").")
|
|
24
|
+
end
|
|
25
|
+
imported_paths = Helper::AppshotHelper.import_captures(
|
|
26
|
+
raw_screenshots: raw_screenshots,
|
|
27
|
+
assets_folder: File.join(studio, "apps", app, "assets"),
|
|
28
|
+
locales: locales,
|
|
29
|
+
slots: slots,
|
|
30
|
+
device: params[:device]
|
|
31
|
+
)
|
|
32
|
+
UI.success("Imported #{imported_paths.count} captures into apps/#{app}/assets")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
render_command = [appshot_path, "render", "--root", studio, "--app", app]
|
|
36
|
+
render_command += locales.flat_map { |locale| ["--locale", locale] }
|
|
37
|
+
render_command += ["--chrome", params[:chrome]] if params[:chrome]
|
|
38
|
+
Actions.sh(*render_command)
|
|
39
|
+
|
|
40
|
+
copied_paths_by_locale = Helper::AppshotHelper.copy_renders(
|
|
41
|
+
rendered_folder: File.join(studio, "output", app),
|
|
42
|
+
output_directory: output_directory,
|
|
43
|
+
locales: locales,
|
|
44
|
+
slots: slots
|
|
45
|
+
)
|
|
46
|
+
UI.success("Copied #{copied_paths_by_locale.values.sum(&:count)} screenshots into #{output_directory}")
|
|
47
|
+
copied_paths_by_locale
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.description
|
|
51
|
+
"Frame fastlane snapshot captures with appshot and hand them to deliver"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.authors
|
|
55
|
+
["Maksim Zhelezniakov"]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.return_value
|
|
59
|
+
"A hash of locale => paths of the framed screenshots copied into output_directory"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.details
|
|
63
|
+
[
|
|
64
|
+
"Takes fastlane snapshot's raw captures into an appshot studio, renders the framed, captioned App Store",
|
|
65
|
+
"screenshots for every locale with appshot (https://github.com/jems19s/appshot-studio), and copies them",
|
|
66
|
+
"into the folder fastlane deliver uploads from. Each capture named \"<simulator>-<name>.png\" goes to the",
|
|
67
|
+
"slot whose screenshot is \"<name>.png\"."
|
|
68
|
+
].join(" ")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.available_options
|
|
72
|
+
[
|
|
73
|
+
FastlaneCore::ConfigItem.new(key: :studio,
|
|
74
|
+
env_name: "APPSHOT_STUDIO",
|
|
75
|
+
description: "appshot studio: the folder holding apps/, templates/ and devices/",
|
|
76
|
+
default_value: "appshot",
|
|
77
|
+
type: String,
|
|
78
|
+
verify_block: proc do |value|
|
|
79
|
+
UI.user_error!("No appshot studio at #{value}") unless File.directory?(value)
|
|
80
|
+
end),
|
|
81
|
+
FastlaneCore::ConfigItem.new(key: :app,
|
|
82
|
+
env_name: "APPSHOT_APP",
|
|
83
|
+
description: "App under apps/ (default: the only one there)",
|
|
84
|
+
optional: true,
|
|
85
|
+
type: String),
|
|
86
|
+
FastlaneCore::ConfigItem.new(key: :raw_screenshots,
|
|
87
|
+
env_name: "APPSHOT_RAW_SCREENSHOTS",
|
|
88
|
+
description: "fastlane snapshot's output_directory, one folder per locale. " \
|
|
89
|
+
"Leave it out to render the screenshots already in the studio",
|
|
90
|
+
optional: true,
|
|
91
|
+
type: String),
|
|
92
|
+
FastlaneCore::ConfigItem.new(key: :device,
|
|
93
|
+
env_name: "APPSHOT_DEVICE",
|
|
94
|
+
description: "Simulator whose captures to use, e.g. \"iPhone 17 Pro Max\". " \
|
|
95
|
+
"Needed only when raw_screenshots holds several devices",
|
|
96
|
+
optional: true,
|
|
97
|
+
type: String),
|
|
98
|
+
FastlaneCore::ConfigItem.new(key: :locales,
|
|
99
|
+
env_name: "APPSHOT_LOCALES",
|
|
100
|
+
description: "Locales to import and render (default: all the app's locales)",
|
|
101
|
+
optional: true,
|
|
102
|
+
type: Array),
|
|
103
|
+
FastlaneCore::ConfigItem.new(key: :output_directory,
|
|
104
|
+
env_name: "APPSHOT_OUTPUT_DIRECTORY",
|
|
105
|
+
description: "Where deliver picks up screenshots; framed PNGs go to " \
|
|
106
|
+
"<output_directory>/<locale>/",
|
|
107
|
+
default_value: "fastlane/screenshots",
|
|
108
|
+
type: String),
|
|
109
|
+
FastlaneCore::ConfigItem.new(key: :appshot_path,
|
|
110
|
+
env_name: "APPSHOT_PATH",
|
|
111
|
+
description: "The appshot command",
|
|
112
|
+
default_value: "appshot",
|
|
113
|
+
type: String),
|
|
114
|
+
FastlaneCore::ConfigItem.new(key: :chrome,
|
|
115
|
+
env_name: "APPSHOT_CHROME",
|
|
116
|
+
description: "Chrome or Chromium to render with (default: found automatically)",
|
|
117
|
+
optional: true,
|
|
118
|
+
type: String)
|
|
119
|
+
]
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def self.example_code
|
|
123
|
+
[
|
|
124
|
+
<<~LANE
|
|
125
|
+
lane :screenshots do
|
|
126
|
+
capture_screenshots(output_directory: "fastlane/raw_screenshots")
|
|
127
|
+
appshot(raw_screenshots: "fastlane/raw_screenshots")
|
|
128
|
+
upload_to_app_store(skip_binary_upload: true, skip_metadata: true)
|
|
129
|
+
end
|
|
130
|
+
LANE
|
|
131
|
+
]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.category
|
|
135
|
+
:screenshots
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def self.is_supported?(platform)
|
|
139
|
+
%i[ios mac].include?(platform)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
require "fastlane_core/ui/ui"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "json"
|
|
4
|
+
require "open3"
|
|
5
|
+
|
|
6
|
+
module Fastlane
|
|
7
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
|
|
8
|
+
|
|
9
|
+
module Helper
|
|
10
|
+
class AppshotHelper
|
|
11
|
+
INSTALL_HINT = "Install it with `brew install jems19s/tap/appshot`, or point appshot_path at the binary.".freeze
|
|
12
|
+
|
|
13
|
+
def self.appshot_version(appshot_path)
|
|
14
|
+
version_output, status = Open3.capture2e(appshot_path, "--version")
|
|
15
|
+
unless status.success?
|
|
16
|
+
UI.user_error!("`#{appshot_path} --version` failed: #{version_output.strip}. #{INSTALL_HINT}")
|
|
17
|
+
end
|
|
18
|
+
version_output.strip
|
|
19
|
+
rescue Errno::ENOENT
|
|
20
|
+
UI.user_error!("appshot not found at '#{appshot_path}'. #{INSTALL_HINT}")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.app_name(studio, requested_app)
|
|
24
|
+
return requested_app if requested_app
|
|
25
|
+
|
|
26
|
+
apps_folder = File.join(studio, "apps")
|
|
27
|
+
app_names = Dir.exist?(apps_folder) ? Dir.children(apps_folder) : []
|
|
28
|
+
app_names = app_names.select { |entry| File.exist?(File.join(apps_folder, entry, "config.json")) }.sort
|
|
29
|
+
return app_names.first if app_names.count == 1
|
|
30
|
+
|
|
31
|
+
UI.user_error!("No appshot app in #{apps_folder} yet — create one with `appshot init`") if app_names.empty?
|
|
32
|
+
UI.user_error!("Several apps in #{apps_folder}: #{app_names.join(', ')} — pick one with app:")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.load_config(studio, app)
|
|
36
|
+
config_path = File.join(studio, "apps", app, "config.json")
|
|
37
|
+
unless File.exist?(config_path)
|
|
38
|
+
UI.user_error!("No appshot app at #{config_path} — create one with `appshot init`")
|
|
39
|
+
end
|
|
40
|
+
JSON.parse(File.read(config_path))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.selected_locales(config, requested_locales)
|
|
44
|
+
configured_locales = config.fetch("locales")
|
|
45
|
+
return configured_locales if requested_locales.nil? || requested_locales.empty?
|
|
46
|
+
|
|
47
|
+
unknown_locales = requested_locales - configured_locales
|
|
48
|
+
unless unknown_locales.empty?
|
|
49
|
+
UI.user_error!("#{unknown_locales.join(', ')} not in the app's locales (#{configured_locales.join(', ')})")
|
|
50
|
+
end
|
|
51
|
+
requested_locales
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.import_captures(raw_screenshots:, assets_folder:, locales:, slots:, device:)
|
|
55
|
+
imported_paths = []
|
|
56
|
+
locales.each do |locale|
|
|
57
|
+
capture_folder = File.join(raw_screenshots, locale)
|
|
58
|
+
unless File.directory?(capture_folder)
|
|
59
|
+
UI.important("No #{capture_folder} — #{locale} keeps the screenshots already in the studio")
|
|
60
|
+
next
|
|
61
|
+
end
|
|
62
|
+
capture_files = Dir.children(capture_folder).select { |file| file.end_with?(".png") }
|
|
63
|
+
slots.each do |slot|
|
|
64
|
+
screenshot = slot.fetch("screenshot")
|
|
65
|
+
capture = capture_for(screenshot, capture_files, capture_folder, device)
|
|
66
|
+
next if capture.nil?
|
|
67
|
+
|
|
68
|
+
locale_assets_folder = File.join(assets_folder, locale)
|
|
69
|
+
FileUtils.mkdir_p(locale_assets_folder)
|
|
70
|
+
FileUtils.cp(File.join(capture_folder, capture), File.join(locale_assets_folder, screenshot))
|
|
71
|
+
imported_paths << File.join(locale_assets_folder, screenshot)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
imported_paths
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# fastlane snapshot saves "<simulator name>-<name>.png"; simulator names can contain hyphens themselves,
|
|
78
|
+
# so captures are matched by their "-<slot screenshot>" ending rather than split at the first hyphen.
|
|
79
|
+
def self.capture_for(screenshot, capture_files, capture_folder, device)
|
|
80
|
+
if device
|
|
81
|
+
capture = "#{device}-#{screenshot}"
|
|
82
|
+
return capture if capture_files.include?(capture)
|
|
83
|
+
|
|
84
|
+
UI.important("No #{capture} in #{capture_folder}")
|
|
85
|
+
return nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
matching_captures = capture_files.select { |file| file.end_with?("-#{screenshot}") }.sort
|
|
89
|
+
if matching_captures.count > 1
|
|
90
|
+
UI.user_error!("Several captures in #{capture_folder} end in -#{screenshot} " \
|
|
91
|
+
"(#{matching_captures.join(', ')}) — set device: to the simulator name")
|
|
92
|
+
end
|
|
93
|
+
UI.important("No capture ending in -#{screenshot} in #{capture_folder}") if matching_captures.empty?
|
|
94
|
+
matching_captures.first
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.copy_renders(rendered_folder:, output_directory:, locales:, slots:)
|
|
98
|
+
rendered_files = slots.map { |slot| "#{slot.fetch('name')}.png" }
|
|
99
|
+
locales.to_h do |locale|
|
|
100
|
+
destination_folder = File.join(output_directory, locale)
|
|
101
|
+
FileUtils.mkdir_p(destination_folder)
|
|
102
|
+
other_files = Dir.children(destination_folder).select { |file|
|
|
103
|
+
file.downcase.end_with?(".png")
|
|
104
|
+
} - rendered_files
|
|
105
|
+
unless other_files.empty?
|
|
106
|
+
UI.important("deliver uploads every PNG in #{destination_folder}, " \
|
|
107
|
+
"so these go up too: #{other_files.sort.join(', ')}")
|
|
108
|
+
end
|
|
109
|
+
copied_paths = rendered_files.map do |file|
|
|
110
|
+
destination = File.join(destination_folder, file)
|
|
111
|
+
FileUtils.cp(File.join(rendered_folder, locale, file), destination)
|
|
112
|
+
destination
|
|
113
|
+
end
|
|
114
|
+
[locale, copied_paths]
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "fastlane/plugin/appshot/version"
|
|
2
|
+
|
|
3
|
+
module Fastlane
|
|
4
|
+
module Appshot
|
|
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::Appshot.all_classes.each do |current|
|
|
15
|
+
require current
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fastlane-plugin-appshot
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Maksim Zhelezniakov
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
email: 48087000+jems19s@users.noreply.github.com
|
|
13
|
+
executables: []
|
|
14
|
+
extensions: []
|
|
15
|
+
extra_rdoc_files: []
|
|
16
|
+
files:
|
|
17
|
+
- CHANGELOG.md
|
|
18
|
+
- LICENSE
|
|
19
|
+
- README.md
|
|
20
|
+
- lib/fastlane/plugin/appshot.rb
|
|
21
|
+
- lib/fastlane/plugin/appshot/actions/appshot_action.rb
|
|
22
|
+
- lib/fastlane/plugin/appshot/helper/appshot_helper.rb
|
|
23
|
+
- lib/fastlane/plugin/appshot/version.rb
|
|
24
|
+
homepage: https://github.com/jems19s/fastlane-plugin-appshot
|
|
25
|
+
licenses:
|
|
26
|
+
- MIT
|
|
27
|
+
metadata:
|
|
28
|
+
rubygems_mfa_required: 'true'
|
|
29
|
+
source_code_uri: https://github.com/jems19s/fastlane-plugin-appshot
|
|
30
|
+
bug_tracker_uri: https://github.com/jems19s/fastlane-plugin-appshot/issues
|
|
31
|
+
changelog_uri: https://github.com/jems19s/fastlane-plugin-appshot/blob/main/CHANGELOG.md
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.1'
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubygems_version: 4.0.11
|
|
47
|
+
specification_version: 4
|
|
48
|
+
summary: Frame fastlane snapshot captures with appshot and hand them to deliver
|
|
49
|
+
test_files: []
|