fastlane-plugin-csv_translation 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d0f16b7ee0ca379dd5ea0519771ff45f609c567715fc10e6245175a9dde17571
4
+ data.tar.gz: 4735dd08f4a574bf92d820937a51131a7ea73525801e507ae67bf20f37e01b48
5
+ SHA512:
6
+ metadata.gz: 82be092d741b44d89dbbc1bf0b476575f4a0decb18c3f12583c87904c0de618f18a3d61af94a033099e516fee67ef55d9e06945446c1ed62adfba86acf122e65
7
+ data.tar.gz: 423d5e8a753a5aeb1ccd4a80ecab0e71ed98f2a9b45696c69ab43bf530ff619ffc973bcfe06e24df0a58151efb0e7652f715970a1a15bc812591ffad3ce20f79
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Manish Rathi
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.
@@ -0,0 +1,131 @@
1
+ # Fastlane `csv_translation` plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-csv_translation) [![Gem Version](https://badge.fury.io/rb/fastlane-plugin-csv_translation.svg)](https://badge.fury.io/rb/fastlane-plugin-csv_translation) [![Twitter: @manish](https://img.shields.io/badge/contact-@manish-blue.svg?style=flat)](https://twitter.com/manish_rathi_)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-csv_translation`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin csv_translation
11
+ ```
12
+
13
+ If you are using fastlane using Gemfile in your project, add it to your project by running:
14
+ ```bash
15
+ bundle exec fastlane add_plugin csv_translation
16
+ ```
17
+
18
+ ## About csv_translation
19
+
20
+ A fastlane plugin to manage translation using a CSV file under git repository. ๐Ÿš€
21
+
22
+ This plugin is inspired by and based on [Keep a CSV](https://en.wikipedia.org/wiki/Comma-separated_values) under git repository. This CSV file can contains translated details for different locales, which can be defined as CSV headers.
23
+ This plugin opens up an opportunity to automate reading from/writing of any `CSV` file with [`fastlane`](https://fastlane.tools).
24
+
25
+ ## CSV file (Example)
26
+ `CSV` file must have locale headers, and can have one identifier header. i.e Below CSV supports `en-US, nl-NL, de-DE, fr-FR, it, es-ES, pt-PT, da, sv, no, zh-Hans, zh-Hant` and `Ticket` column is the unique identifier column which later will be useful to a delete CSV row
27
+
28
+ <img width="1476" alt="Example CSV" src="https://user-images.githubusercontent.com/5364500/81500222-fe912780-92d0-11ea-87a7-952a78b5cdf7.png">
29
+
30
+ ## Actions
31
+ `fastlane-plugin-csv_translation` consists of 4 actions enabling you to manipulate `CSV` file from [`fastlane`](https://fastlane.tools).
32
+
33
+ ### ๐Ÿ“ก get_csv_translation_requests
34
+ Get all the translation info as hash from the CSV file, **print** the `translation_status` if translation_requests found.
35
+
36
+ ``` ruby
37
+ get_csv_translation_requests(
38
+ repository_name: "crazymanish/example-csv-repo", # Specify the CSV git file repo
39
+ file_path: "example.csv" # Specify the CSV file path under the git repo
40
+ )
41
+ ```
42
+
43
+ ``` ruby
44
+ get_csv_translation_requests(
45
+ repository_name: "crazymanish/example-csv-repo", # Specify the CSV git file repo
46
+ branch_name: "master", # Specify the CSV git branch name (dafault `master`)
47
+ file_path: "example.csv", # Specify the CSV file path under the git repo
48
+ show_status: true, # Specify the flag whether to show the translation status or not (dafault `true`)
49
+ show_headers: "Ticket|Timeline" # Specify the CSV headers, will ignored while printing (dafault `Ticket|Timeline`)
50
+ )
51
+ ```
52
+ <img width="794" alt="Translation Status" src="https://user-images.githubusercontent.com/5364500/81500613-8e37d580-92d3-11ea-9f51-fe99e74208bb.png">
53
+
54
+ ### ๐Ÿ“ create_csv_translation_request
55
+ Add a new translation request entry inside the CSV file. It will append a new row in CSV file and then git commit the CSV file changes.
56
+
57
+ ``` ruby
58
+ example_csv_payload = {Ticket: "PRJ-3030", Timeline: "30 April"}
59
+
60
+ create_csv_translation_request(
61
+ repository_name: "crazymanish/example-csv-repo", # Specify the CSV git file repo
62
+ file_path: "example.csv", # Specify the CSV file path under the git repo
63
+ payload: example_csv_payload # Specify the CSV payload
64
+ )
65
+ ```
66
+
67
+ ### ๐Ÿ”rebase_csv_translation_request
68
+ Rebase a translation request entry inside the CSV file. It will append a new row top of target branch in CSV file and then git commit the CSV file changes.
69
+
70
+ ``` ruby
71
+ rebase_csv_translation_request(
72
+ repository_name: "crazymanish/example-csv-repo", # Specify the CSV git file repo
73
+ branch_name: "master", #Specify the target branch (default: master)
74
+ feature_branch_name: "some_feature_branch", #Specify the feature branch name
75
+ file_path: "example.csv", # Specify the CSV file path under the git repo
76
+ identifier: "PRJ-3030" # Specify the CSV row identifier
77
+ )
78
+ ```
79
+
80
+ ### โœ‚๏ธ delete_csv_translation_request
81
+ Delete a new translation request entry from the CSV file based on CSV row Identifier. It will delete the matched row from the CSV file and then git commit the CSV file changes.
82
+
83
+ ``` ruby
84
+ delete_csv_translation_request(
85
+ repository_name: "crazymanish/example-csv-repo", # Specify the CSV git file repo
86
+ file_path: "example.csv", # Specify the CSV file path under the git repo
87
+ identifier: "PRJ-3030" # Specify the CSV row identifier
88
+ )
89
+ ```
90
+
91
+ ## Example
92
+
93
+ You have to **remember to keep your release notes CSV file up-to-date** with translation and let [`fastlane`](https://fastlane.tools) do the rest.
94
+
95
+ ``` ruby
96
+ desc "Release a iOS appstore build to AppStore iTunesConnect with translated release notes."
97
+ lane :release do
98
+ gym # Build the app and create .ipa file
99
+
100
+ version_number = get_version_number # Get project version
101
+
102
+ # Get translated release notes
103
+ release_notes = get_csv_translation_requests(
104
+ repository_name: "crazymanish/ios-app-release-notes-csv-repo",
105
+ file_path: "release_notes/#{version_number}.csv"
106
+ )
107
+ UI.message("Got the translated release notes ๐Ÿ’ช๐Ÿป")
108
+ UI.message(release_notes)
109
+ # TODO: Inject release notes into fastlane `metadata`
110
+
111
+ deliver # Upload ipa file to iTunesConnect with localized release notes fastlane `metadata`
112
+
113
+ slack(message: "Hi team, New version #{version_number} is avaliable!) # share on Slack
114
+ end
115
+ ```
116
+
117
+ ## Issues and Feedback
118
+
119
+ For any other issues and feedback about this plugin, please submit it to this repository.
120
+
121
+ ## Troubleshooting
122
+
123
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
124
+
125
+ ## Using _fastlane_ Plugins
126
+
127
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
128
+
129
+ ## About _fastlane_
130
+
131
+ _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,16 @@
1
+ require 'fastlane/plugin/csv_translation/version'
2
+
3
+ module Fastlane
4
+ module CsvTranslation
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::CsvTranslation.all_classes.each do |current|
15
+ require current
16
+ end
@@ -0,0 +1,120 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/csv_translation_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ CREATE_CSV_TRANSLATION_REQUEST_INFO = :CREATE_CSV_TRANSLATION_REQUEST_INFO
8
+ end
9
+
10
+ class CreateCsvTranslationRequestAction < Action
11
+ def self.run(params)
12
+ # fetching csv file
13
+ csv_file_folder = Helper::CsvTranslationHelper.create_feature_branch(
14
+ repository_name: params[:repository_name],
15
+ branch_name: params[:branch_name],
16
+ feature_branch_name: params[:feature_branch_name]
17
+ )
18
+
19
+ csv_file_path = "#{csv_file_folder}/#{params[:file_path]}"
20
+ csv_payload = params[:payload]
21
+
22
+ # add missing newline if not present, at the end of the file
23
+ File.open(csv_file_path, "r+") do |csv|
24
+ csv.seek(-1, 2)
25
+
26
+ if csv.read(1) != "\n"
27
+ csv.write("\n")
28
+ csv.seek(0)
29
+ end
30
+ end
31
+
32
+ # adding new entry into csv file
33
+ require 'csv'
34
+ headers = CSV.open(csv_file_path, &:readline)
35
+ CSV.open(csv_file_path, 'a', headers: headers, force_quotes: true) do |csv|
36
+ csv << csv_payload
37
+ end
38
+
39
+ # creating csv translation request
40
+ git_message = "New translation request:\n#{csv_payload}"
41
+ git_commit_info = ""
42
+ Dir.chdir(csv_file_folder) do
43
+ GitCommitAction.run(path: ".", message: git_message)
44
+ PushToGitRemoteAction.run(remote: "origin")
45
+ git_commit_info = Actions.last_git_commit_dict
46
+ end
47
+ UI.success("Successfully created a #{git_message} ๐Ÿš€")
48
+
49
+ # building translation request info
50
+ translation_request_info = {
51
+ payload: csv_payload,
52
+ git_commit_info: git_commit_info}
53
+
54
+ Actions.lane_context[SharedValues::CREATE_CSV_TRANSLATION_REQUEST_INFO] = translation_request_info
55
+ return translation_request_info
56
+ end
57
+
58
+ def self.description
59
+ "Create a csv translation request."
60
+ end
61
+
62
+ def self.output
63
+ [
64
+ ['CREATE_CSV_TRANSLATION_REQUEST_INFO', 'Created translation request info i.e payload, git_commit info']
65
+ ]
66
+ end
67
+
68
+ def self.available_options
69
+ [
70
+ FastlaneCore::ConfigItem.new(key: :repository_name,
71
+ env_name: "FL_CREATE_CSV_TRANSLATION_REQUEST_REPOSITORY_NAME",
72
+ description: "The name to your repository, e.g. 'fastlane/fastlane'",
73
+ verify_block: proc do |value|
74
+ UI.user_error!("No repository_name given in input param") unless (value and not value.empty?)
75
+ end),
76
+ FastlaneCore::ConfigItem.new(key: :branch_name,
77
+ env_name: "FL_CREATE_CSV_TRANSLATION_REQUEST_BRANCH_NAME",
78
+ description: "The branch name to your repository, (default master)",
79
+ is_string: true,
80
+ default_value: "master"),
81
+ FastlaneCore::ConfigItem.new(key: :feature_branch_name,
82
+ env_name: "FL_CREATE_CSV_TRANSLATION_REQUEST_FEATURE_BRANCH_NAME",
83
+ description: "The feature branch name for new translation request (Useful if no direct commit allowed in master)",
84
+ is_string: true,
85
+ optional: true),
86
+ FastlaneCore::ConfigItem.new(key: :file_path,
87
+ env_name: "FL_CREATE_CSV_TRANSLATION_REQUEST_FILE_PATH",
88
+ description: "The file path to your csv file",
89
+ is_string: true),
90
+ FastlaneCore::ConfigItem.new(key: :payload,
91
+ env_name: "FL_CREATE_CSV_TRANSLATION_REQUEST_PAYLOAD",
92
+ description: "CSV request info. payload must be a hash containing CSV header key with value",
93
+ is_string: false)
94
+ ]
95
+ end
96
+
97
+ def self.authors
98
+ ["crazymanish"]
99
+ end
100
+
101
+ def self.example_code
102
+ [
103
+ 'create_csv_translation_request(
104
+ repository_name: "fastlane/fastlane",
105
+ file_path: "translation/some_csv_name.csv",
106
+ payload: {"header_name" => "some_value"})',
107
+ 'create_csv_translation_request(
108
+ repository_name: "fastlane/fastlane",
109
+ branch_name: "master",
110
+ file_path: "translation/some_csv_name.csv",
111
+ payload: {"header_name" => "some_value"})'
112
+ ]
113
+ end
114
+
115
+ def self.is_supported?(platform)
116
+ true
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,124 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/csv_translation_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ DELETE_CSV_TRANSLATION_REQUEST_INFO = :DELETE_CSV_TRANSLATION_REQUEST_INFO
8
+ end
9
+
10
+ class DeleteCsvTranslationRequestAction < Action
11
+ def self.run(params)
12
+ # fetching csv file
13
+ csv_file_folder = Helper::CsvTranslationHelper.create_feature_branch(
14
+ repository_name: params[:repository_name],
15
+ branch_name: params[:branch_name],
16
+ feature_branch_name: params[:feature_branch_name]
17
+ )
18
+
19
+ csv_file_path = "#{csv_file_folder}/#{params[:file_path]}"
20
+ csv_row_identifier = params[:identifier]
21
+
22
+ # deleting translation request entry from the csv file
23
+ require 'csv'
24
+
25
+ headers = CSV.open(csv_file_path, &:readline)
26
+ translation_requests = CSV.table(csv_file_path, headers: true)
27
+ translation_requests.delete_if { |row| row.map { |value| value.to_s }.join("").include?(csv_row_identifier) }
28
+
29
+ CSV.open(csv_file_path, "w", write_headers: true, headers: headers, force_quotes: true) do |csv|
30
+ translation_requests.each { |translation_request| csv << translation_request }
31
+ end
32
+
33
+ # deleting translation request from server
34
+ git_commit_info = {}
35
+ Dir.chdir(csv_file_folder) do
36
+ # checking git status for modified files.
37
+ git_status = Actions::sh("git status --porcelain")
38
+ is_git_status_clean = git_status.empty?
39
+
40
+ # log message if translation request not found.
41
+ if is_git_status_clean
42
+ UI.important("Please check \"#{csv_row_identifier}\", not found the translation request. โ‰๏ธ")
43
+ else
44
+ git_message = "Deleted translation request: identifier: #{csv_row_identifier}"
45
+ GitCommitAction.run(path: ".", message: git_message)
46
+ PushToGitRemoteAction.run(remote: "origin")
47
+ git_commit_info = Actions.last_git_commit_dict
48
+
49
+ UI.success("Successfully #{git_message} ๐Ÿš€")
50
+ end
51
+ end
52
+
53
+ # building deleted translation request info
54
+ deleted_translation_request_info = {
55
+ identifier: csv_row_identifier,
56
+ git_commit_info: git_commit_info}
57
+
58
+ Actions.lane_context[SharedValues::DELETE_CSV_TRANSLATION_REQUEST_INFO] = deleted_translation_request_info
59
+ return deleted_translation_request_info
60
+ end
61
+
62
+ def self.description
63
+ "Delete a translation request based on identifier value."
64
+ end
65
+
66
+ def self.output
67
+ [
68
+ ['DELETE_CSV_TRANSLATION_REQUEST_INFO', 'Deleted translation request info i.e identifier, git_commit info']
69
+ ]
70
+ end
71
+
72
+ def self.available_options
73
+ [
74
+ FastlaneCore::ConfigItem.new(key: :repository_name,
75
+ env_name: "FL_DELETE_CSV_TRANSLATION_REQUEST_REPOSITORY_NAME",
76
+ description: "The name to your repository, e.g. 'fastlane/fastlane'",
77
+ verify_block: proc do |value|
78
+ UI.user_error!("No repository_name given in input param") unless (value and not value.empty?)
79
+ end),
80
+ FastlaneCore::ConfigItem.new(key: :branch_name,
81
+ env_name: "FL_DELETE_CSV_TRANSLATION_REQUEST_BRANCH_NAME",
82
+ description: "The branch name to your repository, (default master)",
83
+ is_string: true,
84
+ default_value: "master"),
85
+ FastlaneCore::ConfigItem.new(key: :feature_branch_name,
86
+ env_name: "FL_DELETE_CSV_TRANSLATION_REQUEST_FEATURE_BRANCH_NAME",
87
+ description: "The feature branch name for new translation request (Useful if no direct commit allowed in master)",
88
+ is_string: true,
89
+ optional: true),
90
+ FastlaneCore::ConfigItem.new(key: :file_path,
91
+ env_name: "FL_DELETE_CSV_TRANSLATION_REQUEST_FILE_PATH",
92
+ description: "The file path to your csv file",
93
+ is_string: true),
94
+ FastlaneCore::ConfigItem.new(key: :identifier,
95
+ env_name: "FL_DELETE_CSV_TRANSLATION_REQUEST_IDENTIFIER",
96
+ description: "An identifier value of the CSV file row",
97
+ is_string: true)
98
+ ]
99
+ end
100
+
101
+ def self.authors
102
+ ["crazymanish"]
103
+ end
104
+
105
+ def self.example_code
106
+ [
107
+ 'delete_csv_translation_request(
108
+ repository_name: "fastlane/fastlane",
109
+ file_path: "translation/some_csv_name.csv",
110
+ identifier: "some_identifier_value")',
111
+ 'delete_csv_translation_request(
112
+ repository_name: "fastlane/fastlane",
113
+ branch_name: "master",
114
+ file_path: "translation/some_csv_name.csv",
115
+ identifier: "some_identifier_value")'
116
+ ]
117
+ end
118
+
119
+ def self.is_supported?(platform)
120
+ true
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,117 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/csv_translation_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ GET_CSV_TRANSLATION_REQUESTS_INFO = :GET_CSV_TRANSLATION_REQUESTS_INFO
8
+ end
9
+
10
+ class GetCsvTranslationRequestsAction < Action
11
+ def self.run(params)
12
+ # fetching csv file
13
+ csv_file_folder = Helper::CsvTranslationHelper.fetch_csv_file(
14
+ repository_name: params[:repository_name],
15
+ branch_name: params[:branch_name]
16
+ )
17
+
18
+ require 'csv'
19
+
20
+ # reading csv file
21
+ csv_file_path = "#{csv_file_folder}/#{params[:file_path]}"
22
+ UI.success("Reading csv file from: #{csv_file_path} ๐Ÿ–ฅ")
23
+ translation_requests = CSV.foreach(csv_file_path, headers: true).map { |row| row.to_h }
24
+
25
+ if params[:show_status]
26
+ require 'terminal-table'
27
+
28
+ # printing csv file translation status
29
+ headers = CSV.open(csv_file_path, &:readline)
30
+
31
+ csv_row_identifier = params[:identifier].strip
32
+ unless csv_row_identifier.empty?
33
+ translation_requests = translation_requests.select do |translation_request|
34
+ translation_request.map { |value| value.to_s }.join("").include?(csv_row_identifier)
35
+ end
36
+ end
37
+
38
+ printing_translation_requests = translation_requests.map do |translation_request|
39
+ translation_request.map do |key, value|
40
+ if key.to_s.match?(params[:show_headers])
41
+ value
42
+ else
43
+ value.to_s.empty? ? "โŒ": "โœ…"
44
+ end
45
+ end
46
+ end
47
+ table = Terminal::Table.new(title: "Translation status", headings: headers, rows: printing_translation_requests)
48
+ puts table
49
+ end
50
+
51
+ Actions.lane_context[SharedValues::GET_CSV_TRANSLATION_REQUESTS_INFO] = translation_requests
52
+ return translation_requests
53
+ end
54
+
55
+ def self.description
56
+ "Get CSV translation requests info"
57
+ end
58
+
59
+ def self.available_options
60
+ [
61
+ FastlaneCore::ConfigItem.new(key: :repository_name,
62
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_REPOSITORY_NAME",
63
+ description: "The name to your repository, e.g. 'fastlane/fastlane'",
64
+ verify_block: proc do |value|
65
+ UI.user_error!("No repository_name given in input param") unless (value and not value.empty?)
66
+ end),
67
+ FastlaneCore::ConfigItem.new(key: :branch_name,
68
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_BRANCH_NAME",
69
+ description: "The branch name to your repository, (default master)",
70
+ is_string: true,
71
+ default_value: "master"),
72
+ FastlaneCore::ConfigItem.new(key: :file_path,
73
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_FILE_PATH",
74
+ description: "The file path to your csv file",
75
+ is_string: true),
76
+ FastlaneCore::ConfigItem.new(key: :show_status,
77
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_SHOW_STATUS",
78
+ description: "The flag whether to show the translation status, (default 'true')",
79
+ optional: true,
80
+ default_value: true,
81
+ is_string: false),
82
+ FastlaneCore::ConfigItem.new(key: :show_headers,
83
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_SHOW_HEADERS",
84
+ description: "Show CSV headers translation value while printing, (default 'Ticket|Timeline')",
85
+ is_string: true,
86
+ default_value: "Ticket|Timeline"),
87
+ FastlaneCore::ConfigItem.new(key: :identifier,
88
+ env_name: "FL_GET_CSV_TRANSLATION_REQUESTS_IDENTIFIER",
89
+ description: "An identifier value of the CSV file row",
90
+ is_string: true,
91
+ optional: true,
92
+ default_value: "")
93
+ ]
94
+ end
95
+
96
+ def self.authors
97
+ ["crazymanish"]
98
+ end
99
+
100
+ def self.example_code
101
+ [
102
+ 'get_csv_translation_requests(
103
+ repository_name: "fastlane/fastlane",
104
+ file_path: "translation/some_csv_name.csv")',
105
+ 'get_csv_translation_requests(
106
+ repository_name: "fastlane/fastlane",
107
+ branch_name: "master",
108
+ file_path: "translation/some_csv_name.csv")'
109
+ ]
110
+ end
111
+
112
+ def self.is_supported?(platform)
113
+ true
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,134 @@
1
+ require 'fastlane/action'
2
+ require_relative '../helper/csv_translation_helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ module SharedValues
7
+ REBASE_CSV_TRANSLATION_REQUEST_INFO = :REBASE_CSV_TRANSLATION_REQUEST_INFO
8
+ end
9
+
10
+ class RebaseCsvTranslationRequestAction < Action
11
+ def self.run(params)
12
+ # fetching csv file
13
+ csv_file_folder = Helper::CsvTranslationHelper.fetch_csv_file(
14
+ repository_name: params[:repository_name],
15
+ branch_name: params[:feature_branch_name]
16
+ )
17
+
18
+ csv_file_path = "#{csv_file_folder}/#{params[:file_path]}"
19
+ csv_row_identifier = params[:identifier]
20
+
21
+ require 'csv'
22
+
23
+ # picking translation request-identifier entry from the feature_branch csv file
24
+ feature_branch_translation_requests = CSV.table(csv_file_path, headers: true)
25
+ feature_branch_translation_requests = feature_branch_translation_requests.select { |row| row.map { |value| value.to_s }.join("").include?(csv_row_identifier) }
26
+
27
+ # rebasing CSV file
28
+ git_commit_info = {}
29
+ Dir.chdir(csv_file_folder) do
30
+ # Step1: Checkout the target branch csv file
31
+ sh("git fetch --all")
32
+ sh("git checkout #{params[:branch_name]} -- #{params[:file_path]}")
33
+
34
+ # Step2: Commit csv file so rebase can be performed
35
+ git_message = "Rebase translation request: identifier:\n#{csv_row_identifier}"
36
+ GitCommitAction.run(path: ".", message: git_message)
37
+
38
+ # Step3: Perfoms rebasing, take all changes from target branch
39
+ sh("git rebase -X theirs " + params[:branch_name])
40
+
41
+ # Step4: Add missing newline if not present, at the end of the file
42
+ Helper::CsvTranslationHelper.append_missing_eof(csv_file_path)
43
+
44
+ # Step5: Append back feature branch translation_requests
45
+ all_translation_requests = CSV.table(csv_file_path, headers: true)
46
+ all_translation_requests.delete_if { |row| row.map { |value| value.to_s }.join("").include?(csv_row_identifier) }
47
+
48
+ headers = CSV.open(csv_file_path, &:readline)
49
+ CSV.open(csv_file_path, "w", write_headers: true, headers: headers, force_quotes: true) do |csv|
50
+ all_translation_requests.each { |translation_request| csv << translation_request }
51
+ feature_branch_translation_requests.each { |translation_request| csv << translation_request }
52
+ end
53
+
54
+ # Step6: Commit and push to remote
55
+ GitCommitAction.run(path: ".", message: git_message)
56
+ PushToGitRemoteAction.run(remote: "origin", force: true)
57
+
58
+ git_commit_info = Actions.last_git_commit_dict
59
+ UI.success("Successfully #{git_message} ๐Ÿš€")
60
+ end
61
+
62
+ # building deleted translation request info
63
+ rebase_translation_request_info = {
64
+ identifier: csv_row_identifier,
65
+ git_commit_info: git_commit_info}
66
+
67
+ Actions.lane_context[SharedValues::REBASE_CSV_TRANSLATION_REQUEST_INFO] = rebase_translation_request_info
68
+ return rebase_translation_request_info
69
+ end
70
+
71
+ def self.description
72
+ "Rebase a translation request based on identifier value."
73
+ end
74
+
75
+ def self.output
76
+ [
77
+ ['REBASE_CSV_TRANSLATION_REQUEST_INFO', 'Rebased translation request info i.e identifier, git_commit info']
78
+ ]
79
+ end
80
+
81
+ def self.available_options
82
+ [
83
+ FastlaneCore::ConfigItem.new(key: :repository_name,
84
+ env_name: "FL_REBASE_CSV_TRANSLATION_REQUEST_REPOSITORY_NAME",
85
+ description: "The name to your repository, e.g. 'fastlane/fastlane'",
86
+ verify_block: proc do |value|
87
+ UI.user_error!("No repository_name given in input param") unless (value and not value.empty?)
88
+ end),
89
+ FastlaneCore::ConfigItem.new(key: :branch_name,
90
+ env_name: "FL_REBASE_CSV_TRANSLATION_REQUEST_BRANCH_NAME",
91
+ description: "The branch name to your repository, (default master)",
92
+ is_string: true,
93
+ default_value: "master"),
94
+ FastlaneCore::ConfigItem.new(key: :feature_branch_name,
95
+ env_name: "FL_REBASE_CSV_TRANSLATION_REQUEST_FEATURE_BRANCH_NAME",
96
+ description: "The feature branch name for new translation request (Useful if no direct commit allowed in master)",
97
+ is_string: true),
98
+ FastlaneCore::ConfigItem.new(key: :file_path,
99
+ env_name: "FL_REBASE_CSV_TRANSLATION_REQUEST_FILE_PATH",
100
+ description: "The file path to your csv file",
101
+ is_string: true),
102
+ FastlaneCore::ConfigItem.new(key: :identifier,
103
+ env_name: "FL_REBASE_CSV_TRANSLATION_REQUEST_IDENTIFIER",
104
+ description: "An identifier value of the CSV file row",
105
+ is_string: true)
106
+ ]
107
+ end
108
+
109
+ def self.authors
110
+ ["crazymanish"]
111
+ end
112
+
113
+ def self.example_code
114
+ [
115
+ 'rebase_csv_translation_request(
116
+ repository_name: "fastlane/fastlane",
117
+ feature_branch_name: "some_feature_branch",
118
+ file_path: "translation/some_csv_name.csv",
119
+ identifier: "some_identifier_value")',
120
+ 'rebase_csv_translation_request(
121
+ repository_name: "fastlane/fastlane",
122
+ branch_name: "master",
123
+ feature_branch_name: "some_feature_branch",
124
+ file_path: "translation/some_csv_name.csv",
125
+ identifier: "some_identifier_value")'
126
+ ]
127
+ end
128
+
129
+ def self.is_supported?(platform)
130
+ true
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,61 @@
1
+ require 'fastlane_core/ui/ui'
2
+
3
+ module Fastlane
4
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
5
+
6
+ module Helper
7
+ class CsvTranslationHelper
8
+
9
+ def self.csv_file_directory_name
10
+ return ".fl_clone_csv_file"
11
+ end
12
+
13
+ def self.csv_file_directory_path
14
+ return File.join(Dir.pwd, self.csv_file_directory_name)
15
+ end
16
+
17
+ def self.fetch_csv_file(params)
18
+ repository_name = params[:repository_name]
19
+ branch_name = params[:branch_name]
20
+
21
+ # Setup csv_file folder for fresh git clone.
22
+ git_clone_folder = self.csv_file_directory_path
23
+ FileUtils.rm_rf(git_clone_folder) if File.directory?(git_clone_folder)
24
+ Dir.mkdir(self.csv_file_directory_name)
25
+
26
+ UI.success("Fetching csv file from git repo... โณ")
27
+ git_url = "git@github.com:#{repository_name}"
28
+ Fastlane::Actions::sh("git clone #{git_url.shellescape} #{git_clone_folder.shellescape}")
29
+ Fastlane::Actions::sh("cd #{git_clone_folder.shellescape} && git checkout #{branch_name}")
30
+
31
+ return git_clone_folder
32
+ end
33
+
34
+ def self.create_feature_branch(params)
35
+ git_clone_folder = self.fetch_csv_file(params)
36
+
37
+ # creating and checkout new branch
38
+ branch_name = params[:feature_branch_name]
39
+ Fastlane::Actions::sh("cd #{git_clone_folder.shellescape} && git checkout -b #{branch_name}")
40
+
41
+ # pushing newly created branch
42
+ Fastlane::Actions::sh("cd #{git_clone_folder.shellescape} && git push -u origin #{branch_name}")
43
+
44
+ return git_clone_folder
45
+ end
46
+
47
+ # add missing newline if not present, at the end of the file
48
+ def self.append_missing_eof(file_path)
49
+ File.open(file_path, "r+") do |file|
50
+ file.seek(-1, 2)
51
+
52
+ if file.read(1) != "\n"
53
+ file.write("\n")
54
+ file.seek(0)
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module CsvTranslation
3
+ VERSION = "0.4.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-csv_translation
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Manish Rathi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: rspec_junit_formatter
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: rake
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: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '='
88
+ - !ruby/object:Gem::Version
89
+ version: 0.49.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.49.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-require_tools
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: simplecov
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: fastlane
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 2.146.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 2.146.1
139
+ description:
140
+ email: manishrathi19902013@gmail.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - LICENSE
146
+ - README.md
147
+ - lib/fastlane/plugin/csv_translation.rb
148
+ - lib/fastlane/plugin/csv_translation/actions/create_csv_translation_request.rb
149
+ - lib/fastlane/plugin/csv_translation/actions/delete_csv_translation_request.rb
150
+ - lib/fastlane/plugin/csv_translation/actions/get_csv_translation_requests.rb
151
+ - lib/fastlane/plugin/csv_translation/actions/rebase_csv_translation_request.rb
152
+ - lib/fastlane/plugin/csv_translation/helper/csv_translation_helper.rb
153
+ - lib/fastlane/plugin/csv_translation/version.rb
154
+ homepage: https://github.com/crazymanish/fastlane-plugin-csv_translation
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubygems_version: 3.0.3
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: "A fastlane plugin to manage translation using a CSV file under git repository.
177
+ \U0001F680"
178
+ test_files: []