feat: implement deployement pipeline (#2)
This commit is contained in:
parent
ee58f96126
commit
155d048c18
@ -7,7 +7,7 @@ module Fastlane
|
|||||||
def self.run(params)
|
def self.run(params)
|
||||||
# Check parameters
|
# Check parameters
|
||||||
unless Helper::AndroidCdHelper.is_set(params[:beta_type])
|
unless Helper::AndroidCdHelper.is_set(params[:beta_type])
|
||||||
UI.error("Parameters beta_type cannot be null")
|
UI.error("❌ Parameters beta_type cannot be null")
|
||||||
puts("Error on beta type parameter")
|
puts("Error on beta type parameter")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
# Ruby CircleCI 2.0 configuration file
|
|
||||||
#
|
|
||||||
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
|
|
||||||
#
|
|
||||||
version: 2
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
docker:
|
|
||||||
# specify the version you desire here
|
|
||||||
- image: circleci/ruby:2.5
|
|
||||||
|
|
||||||
working_directory: ~/repo
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
|
|
||||||
# Download and cache dependencies
|
|
||||||
- restore_cache:
|
|
||||||
keys:
|
|
||||||
- v1-dependencies-{{ checksum "Gemfile" }}
|
|
||||||
# fallback to using the latest cache if no exact match is found
|
|
||||||
- v1-dependencies-
|
|
||||||
|
|
||||||
- run:
|
|
||||||
name: install dependencies
|
|
||||||
command: bundle check || bundle install --jobs=4 --retry=3 --path vendor/bundle
|
|
||||||
|
|
||||||
- save_cache:
|
|
||||||
paths:
|
|
||||||
- ./vendor
|
|
||||||
key: v1-dependencies-{{ checksum "Gemfile" }}
|
|
||||||
|
|
||||||
# run tests!
|
|
||||||
- run:
|
|
||||||
name: run tests
|
|
||||||
command: bundle exec rake
|
|
||||||
|
|
||||||
# collect reports
|
|
||||||
- store_test_results:
|
|
||||||
path: ~/repo/test-results
|
|
||||||
- store_artifacts:
|
|
||||||
path: ~/repo/test-results
|
|
||||||
destination: test-results
|
|
@ -2,5 +2,7 @@ source('https://rubygems.org')
|
|||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
|
gem 'json'
|
||||||
|
|
||||||
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
|
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
|
||||||
eval_gemfile(plugins_path) if File.exist?(plugins_path)
|
eval_gemfile(plugins_path) if File.exist?(plugins_path)
|
||||||
|
@ -0,0 +1,116 @@
|
|||||||
|
require 'fastlane/action'
|
||||||
|
require_relative '../helper/ios_cd_helper'
|
||||||
|
|
||||||
|
module Fastlane
|
||||||
|
module Actions
|
||||||
|
class BuildAndDeploy < Action
|
||||||
|
def self.run(params)
|
||||||
|
# Check parameters
|
||||||
|
unless Helper::IosCdHelper.is_set(params[:beta_type])
|
||||||
|
UI.error("❌ Parameters beta_type cannot be null")
|
||||||
|
puts("Error on beta type parameter")
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.message("⌛️ Building and deploying to Store in #{params[:beta_type]}..")
|
||||||
|
|
||||||
|
# Decrypt the keys archive and Extract the keys archive
|
||||||
|
Helper::IosCdHelper.decrypt_ios_keys('.')
|
||||||
|
|
||||||
|
# Retrieve credentials
|
||||||
|
creds = Helper::IosCdHelper.parseIosCredentials
|
||||||
|
|
||||||
|
UI.message(creds.to_s)
|
||||||
|
|
||||||
|
# Ensure temporary keychain exists
|
||||||
|
Fastlane::Actions.ensure_temp_keychain(creds['temp_keychain_user'], creds['temp_keychain_password'])
|
||||||
|
|
||||||
|
# Obtain App Store Connect API key
|
||||||
|
api_key = Fastlane::Actions.app_store_connect_api_key(
|
||||||
|
key_id: creds['apple_key_id'],
|
||||||
|
issuer_id: creds['apple_issuer_id'],
|
||||||
|
key_content: creds['apple_key_content'],
|
||||||
|
duration: 1200,
|
||||||
|
in_house: false
|
||||||
|
)
|
||||||
|
|
||||||
|
# Increment build number for latest TestFlight build
|
||||||
|
Fastlane::Actions.increment_build_number({
|
||||||
|
build_number: Fastlane::Actions.latest_testflight_build_number + 1,
|
||||||
|
xcodeproj: "Runner.xcodeproj"
|
||||||
|
})
|
||||||
|
|
||||||
|
# Install Cocoapods
|
||||||
|
Fastlane::Actions.cocoapods(
|
||||||
|
clean_install: true
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set up code signing using match
|
||||||
|
# Configures and runs `match` which manages code signing certificates and provisioning profiles for the project.
|
||||||
|
# The function takes the app's bundle identifier, an authorization token for the project's Git repository, and the name and password for a temporary keychain used to store the signing certificate.
|
||||||
|
# It uses the App Store Connect API key to access the App Store and increment the build number.
|
||||||
|
# It then runs `gym` to build and sign the app using the selected provisioning profile, and finally, uses `pilot` to upload the app to TestFlight for beta testing.
|
||||||
|
Fastlane::Actions.match(
|
||||||
|
type: 'appstore',
|
||||||
|
app_identifier: creds['app_identifier_extensions'],
|
||||||
|
git_basic_authorization: Base64.strict_encode64(ENV["GIT_AUTHORIZATION"]),
|
||||||
|
keychain_name: creds['temp_keychain_user'],
|
||||||
|
keychain_password: creds['temp_keychain_password'],
|
||||||
|
api_key: api_key
|
||||||
|
)
|
||||||
|
|
||||||
|
# Build and export app using Gym
|
||||||
|
# Builds and packages an iOS app or framework for distribution to the App Store, TestFlight, or Enterprise distribution.
|
||||||
|
Fastlane::Actions.gym(
|
||||||
|
configuration: "Release",
|
||||||
|
workspace: "Runner.xcworkspace",
|
||||||
|
scheme: "your_schema",
|
||||||
|
export_method: "app-store",
|
||||||
|
export_options: {
|
||||||
|
provisioningProfiles: creds['provisioning_profiles']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Upload build to App Store Connect using Pilot
|
||||||
|
Fastlane::Actions.pilot(
|
||||||
|
apple_id: creds['developer_app_id'].to_s,
|
||||||
|
app_identifier: creds['developer_app_identifier'].to_s,
|
||||||
|
skip_waiting_for_build_processing: true,
|
||||||
|
skip_submission: true,
|
||||||
|
distribute_external: false,
|
||||||
|
notify_external_testers: false,
|
||||||
|
ipa: "./Runner.ipa"
|
||||||
|
)
|
||||||
|
|
||||||
|
Fastlane::Actions.delete_temp_keychain
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.description
|
||||||
|
"Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing."
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.authors
|
||||||
|
["SAS Wyatt Studio"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.return_value
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.details
|
||||||
|
"The Fastlane Testflight / Appstore deloyment action streamlines the build and deployment to internal, external and production channels. Allow you to promote builds on testflight beta tests."
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.available_options
|
||||||
|
[
|
||||||
|
FastlaneCore::ConfigItem.new(key: :beta_type,
|
||||||
|
env_name: "IOS_CD_TEST_TYPE",
|
||||||
|
optional: false,
|
||||||
|
description: "Type of test (internal, external, production)")
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.is_supported?(platform)
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,47 +0,0 @@
|
|||||||
require 'fastlane/action'
|
|
||||||
require_relative '../helper/ios_cd_helper'
|
|
||||||
|
|
||||||
module Fastlane
|
|
||||||
module Actions
|
|
||||||
class IosCdAction < Action
|
|
||||||
def self.run(params)
|
|
||||||
UI.message("The ios_cd plugin is working!")
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.description
|
|
||||||
"Testflight and AppStore deployment plugin for Fastlane, simplifying the build and deployment porcess to internal, external, and production channels, and promoting builds for testing."
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.authors
|
|
||||||
["Malo Léon"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.return_value
|
|
||||||
# If your method provides a return value, you can describe here what it does
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.details
|
|
||||||
# Optional:
|
|
||||||
"The Fastlane Testflight / Appstore deloyment action streamlines the build and deployment to internal, external and production channels. Allow you to promote builds on testflight beta tests."
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.available_options
|
|
||||||
[
|
|
||||||
# FastlaneCore::ConfigItem.new(key: :your_option,
|
|
||||||
# env_name: "IOS_CD_YOUR_OPTION",
|
|
||||||
# description: "A description of your option",
|
|
||||||
# optional: false,
|
|
||||||
# type: String)
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.is_supported?(platform)
|
|
||||||
# Adjust this if your plugin only works for a particular platform (iOS vs. Android, for example)
|
|
||||||
# See: https://docs.fastlane.tools/advanced/#control-configuration-by-lane-and-by-platform
|
|
||||||
#
|
|
||||||
# [:ios, :mac, :android].include?(platform)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,15 +1,71 @@
|
|||||||
|
require 'fastlane/action'
|
||||||
|
require 'json'
|
||||||
require 'fastlane_core/ui/ui'
|
require 'fastlane_core/ui/ui'
|
||||||
|
|
||||||
module Fastlane
|
module Fastlane
|
||||||
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
|
||||||
|
|
||||||
module Helper
|
module Helper
|
||||||
class IosCdHelper
|
class IosCdHelper
|
||||||
# class methods that you define here become available in your action
|
# Define method to delete temporary keychain
|
||||||
# as `Helper::IosCdHelper.your_method`
|
def delete_temp_keychain(name)
|
||||||
#
|
if File.exist?(File.expand_path("~/Library/Keychains/#{name}-db"))
|
||||||
def self.show_message
|
Fastlane::Actions.delete_keychain(
|
||||||
UI.message("Hello from the ios_cd plugin helper!")
|
name: name
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Define method to create temporary keychain
|
||||||
|
def create_temp_keychain(name, password)
|
||||||
|
Fastlane::Actions.create_keychain(
|
||||||
|
name: name,
|
||||||
|
password: password,
|
||||||
|
unlock: false,
|
||||||
|
timeout: 0
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Define method to ensure that temporary keychain exists
|
||||||
|
def ensure_temp_keychain(name, password)
|
||||||
|
delete_temp_keychain(name)
|
||||||
|
create_temp_keychain(name, password)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if a parameter is set or not
|
||||||
|
def self.is_set(variable)
|
||||||
|
str_variable = variable
|
||||||
|
str_variable = variable.strip if variable.class.to_s == "String"
|
||||||
|
variable && !(str_variable.nil? || str_variable.empty?)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Decrypts ios credentials
|
||||||
|
def self.decrypt_ios_keys(ios_directory)
|
||||||
|
# Define the GPG command with options
|
||||||
|
gpg_command = "gpg --quiet --batch --yes --decrypt --passphrase=#{ENV['IOS_KEYS_SECRET_PASSPHRASE']} \
|
||||||
|
--output #{ios_directory}/ios_keys.zip #{ios_directory}/ios_keys.zip.gpg"
|
||||||
|
|
||||||
|
# Execute the GPG command using system
|
||||||
|
system(gpg_command)
|
||||||
|
|
||||||
|
# Check if the command executed successfully
|
||||||
|
if $?.success?
|
||||||
|
|
||||||
|
# Move the extracted files to the current directory
|
||||||
|
`jar xvf #{ios_directory} && mv #{ios_directory}/ios_keys/* #{ios_directory}`
|
||||||
|
else
|
||||||
|
puts("Erreur lors de la décompression du fichier GPG")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse credential file
|
||||||
|
def parseIosCredentials(ios_directory)
|
||||||
|
if File.exists?("#{ios_directory}/ios_crendentials.json")
|
||||||
|
# Read file and decrypt it
|
||||||
|
file = File.read("#{ios_directory}/ios_crendentials.json")
|
||||||
|
JSON.parse(file)
|
||||||
|
|
||||||
|
else
|
||||||
|
UI.error("❌ Ios credentials doesn't exist")
|
||||||
|
puts("json file doesn't exist")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
describe Fastlane::Actions::IosCdAction do
|
describe Fastlane::Actions::BuildAndDeploy do
|
||||||
describe '#run' do
|
describe '#run' do
|
||||||
it 'prints a message' do
|
it 'prints a message' do
|
||||||
expect(Fastlane::UI).to receive(:message).with("The ios_cd plugin is working!")
|
expect(Fastlane::UI).to receive(:message).with("The ios_cd plugin is working!")
|
||||||
|
|
||||||
Fastlane::Actions::IosCdAction.run(nil)
|
Fastlane::Actions::BuildAndDeploy.run(nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user