diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..d475e062 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,90 @@ +stages: +# - test + - download + - build + - deploy + +#test: +# stage: test +# script: +# - echo "This job tests something" +# tags: +# - xcode_12_2 + +download_artifacts: + stage: download + script: + - ./Scripts/download_dependencies.sh + only: + - branches + - develop + tags: + - bash_shell + environment: + name: oneartifactory + url: https://oneartifactoryprod.verizon.com/artifactory + variables: + ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory + +build_project: + stage: build + script: + - ./Scripts/build_aggregate.sh + only: + - branches + - develop + tags: + - xcode_12_2 + +deploy_snapshot: + stage: deploy + script: + - cd Scripts && ./upload_core_ui_frameworks.sh + only: + - branches + - develop + tags: + - bash_shell + environment: + name: oneartifactory + url: https://oneartifactoryprod.verizon.com/artifactory + variables: + ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory + +#promote_snapshot: +# stage: go live +# # Prevent artifacts from needing to re-download. Everything we need is in Artifactory. +# dependencies: [] +# script: +# # Grab the framework version from the xcode project. +# - framework_ver=$(cd RemoteView && agvtool vers -terse) +# - cd Scripts && ./promote_remote_view_frameworks.sh $framework_ver +# only: +# - tags +# tags: +# - bash_shell +# environment: +# name: oneartifactory +# url: https://oneartifactoryprod.verizon.com/artifactory +# variables: +# ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory +# +#create_version_tag: +# stage: tag +# when: manual +# # Prevent artifacts from needing to re-download. +# dependencies: [] +# script: +# # Grab the framework version from the xcode project and create a tag of the version. +# - framework_ver=$(cd RemoteView && agvtool vers -terse) +# - git tag -a "v${framework_ver}" -m "Version ${framework_ver} created by gitlab-ci Build" +# # Extract the git repo url to ssh version (git@gitlab.verizon.com) +# - ci_push_repo="git@${CI_SERVER_HOST}:${CI_PROJECT_PATH}.git" +# - echo $ci_push_repo +# # Set the remote url for pushing assuming the gitlab runner has SSH access to the repo. +# - git remote set-url --push origin $ci_push_repo +# - git push origin "v${framework_ver}" +# only: +# - develop +# tags: +# - bash_shell diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 281a6ffc..ef9b278f 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -124,6 +124,8 @@ 0AE98BB323FF0934004C5109 /* ExternalLinkModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */; }; 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB423FF18D2004C5109 /* Arrow.swift */; }; 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */; }; + 1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; }; + 1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; }; 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; }; 27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; }; 27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; }; @@ -690,6 +692,8 @@ 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLinkModel.swift; sourceTree = ""; }; 0AE98BB423FF18D2004C5109 /* Arrow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arrow.swift; sourceTree = ""; }; 0AE98BB623FF18E9004C5109 /* ArrowModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrowModel.swift; sourceTree = ""; }; + 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; }; + 1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; }; 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = ""; }; 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = ""; }; 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = ""; }; @@ -1295,6 +1299,8 @@ 0AE98BAD23FEF92B004C5109 /* Link */ = { isa = PBXGroup; children = ( + 1D6D258726899B0B00DEBB08 /* ImageButton.swift */, + 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */, D28A838823CCCFCB00DFE4FC /* LinkModel.swift */, C07065C32395677300FBF997 /* Link.swift */, 0AE98BB223FF0934004C5109 /* ExternalLinkModel.swift */, @@ -2896,6 +2902,7 @@ D2C78CD224228BBD00B69FDE /* ActionOpenPanelModel.swift in Sources */, AA617AB02453010A00910B8F /* ListDeviceComplexLinkSmall.swift in Sources */, D23A8FD9260CE004007E14CE /* MFStyler+PaddingExtension.swift in Sources */, + 1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, @@ -2940,6 +2947,7 @@ BB2BF0EC2452A9D5001D0FC2 /* ListDeviceComplexButtonSmallModel.swift in Sources */, 943784F6236B77BB006A1E82 /* WheelAnimationHandler.swift in Sources */, 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, + 1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */, AA07EA912510A442009A2AE3 /* StarModel.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, 011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift new file mode 100644 index 00000000..2d71ee6e --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift @@ -0,0 +1,54 @@ +// +// ImageButton.swift +// MobileFirstFramework +// +// Created by Chintakrinda, Arun Kumar (Arun) on 07/10/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ImageButton: Button { + + public let image = LoadImageView(pinnedEdges: .all) + + open override func setupView() { + super.setupView() + insertSubview(image, at: 0) + image.isUserInteractionEnabled = false + NSLayoutConstraint.constraintPinSubview(toSuperview: image) + } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let castModel = model as? ImageButtonModel else { + super.set(with: model, delegateObject, additionalData) + return + } + image.setOptional(with: castModel.image, delegateObject, additionalData) + castModel.updateUI = { [weak self] in + MVMCoreDispatchUtility.performBlock(onMainThread: { + self?.setState() + }) + } + + super.set(with: model, delegateObject, additionalData) + FormValidator.setupValidation(for: castModel, delegate: delegateObject?.formHolderDelegate) + + } + + private func setState() { + guard let castModel = model as? ImageButtonModel else { + return + } + if castModel.enabled { + if let enabledTintColor = castModel.enabledTintColor { + image.imageView.tintColor = enabledTintColor.uiColor + } + } else if let disabledTintColor = castModel.disabledTintColor { + image.imageView.tintColor = disabledTintColor.uiColor + } + } + + + +} diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift new file mode 100644 index 00000000..d8217d0d --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift @@ -0,0 +1,95 @@ +// +// ImageButtonModel.swift +// MobileFirstFramework +// +// Created by Chintakrinda, Arun Kumar (Arun) on 07/10/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +open class ImageButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String = "imageButton" + public var backgroundColor: Color? + + public var image: ImageViewModel? + + public var accessibilityText: String? + public var action: ActionModelProtocol + public var enabled: Bool = true + public var enabledTintColor: Color? + public var disabledTintColor: Color? + + public var groupName: String = "" + + public func setValidity(_ valid: Bool, group: FormGroupRule) { + enabled = valid + updateUI?() + } + + public var updateUI: ActionBlock? + + public init(image: ImageViewModel?, action: ActionModelProtocol) { + self.image = image + self.action = action + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case image + case backgroundColor + case accessibilityText + case action + case enabled + case groupName + case enabledTintColor + case disabledTintColor + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + image = try typeContainer.decodeIfPresent(ImageViewModel.self, forKey: .image) + accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) + action = try typeContainer.decodeModel(codingKey: .action) + + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } + + if let enabledTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTintColor) { + self.enabledTintColor = enabledTintColor + } + + if let disabledTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTintColor) { + self.disabledTintColor = disabledTintColor + } + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(image, forKey: .image) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) + try container.encode(enabled, forKey: .enabled) + try container.encodeModel(action, forKey: .action) + try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encodeIfPresent(enabledTintColor, forKey: .enabledTintColor) + try container.encodeIfPresent(disabledTintColor, forKey: .disabledTintColor) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index e8f940a2..c0f001e7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -8,6 +8,10 @@ import Foundation +public protocol RadioBoxSelectionDelegate: class { + func selected(radioBox: RadioBoxModel) +} + open class RadioBoxes: View { public var collectionView: CollectionView! @@ -19,14 +23,14 @@ open class RadioBoxes: View { private var radioBoxesModel: RadioBoxesModel? { return model as? RadioBoxesModel } - + public weak var radioDelegate: RadioBoxSelectionDelegate? private var delegateObject: MVMCoreUIDelegateObject? /// The models for the molecules. public var boxes: [RadioBoxModel]? - + private var size: CGFloat? - + open override func layoutSubviews() { super.layoutSubviews() // Accounts for any collection size changes @@ -37,7 +41,7 @@ open class RadioBoxes: View { open func updateAccessibilityValue(collectionView: UICollectionView, cell: RadioBoxCollectionViewCell, indexPath: IndexPath) { guard let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"), - let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: indexPath.row + 1)) else { return } + let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: indexPath.row + 1)) else { return } let total = self.collectionView(collectionView, numberOfItemsInSection: indexPath.section) cell.accessibilityValue = String(format: format, indexString, total) } @@ -60,7 +64,7 @@ open class RadioBoxes: View { guard let model = model as? RadioBoxesModel else { return } boxes = model.boxes FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) - + backgroundColor = model.backgroundColor?.uiColor registerCells() @@ -85,7 +89,7 @@ open class RadioBoxes: View { layout.minimumInteritemSpacing = itemSpacing return layout } - + /// Creates the collection view. open func createCollectionView() -> CollectionView { let collection = CollectionView(frame: .zero, collectionViewLayout: createCollectionViewLayout()) @@ -98,7 +102,7 @@ open class RadioBoxes: View { open func registerCells() { collectionView.register(RadioBoxCollectionViewCell.self, forCellWithReuseIdentifier: "RadioBoxCollectionViewCell") } - + // MARK: - JSON Setters open func setHeight() { guard let boxes = boxes, boxes.count > 0 else { @@ -127,7 +131,7 @@ extension RadioBoxes: UICollectionViewDataSource { open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = boxes?[indexPath.row], - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else { fatalError() } cell.reset() @@ -162,6 +166,8 @@ extension RadioBoxes: UICollectionViewDelegate { cell.radioBox.selectBox() _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) cell.updateAccessibility() + guard let radioBox = boxes?[indexPath.row] else { return } + radioDelegate?.selected(radioBox: radioBox) } open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index f3ce24e5..804075ff 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -13,7 +13,8 @@ import UIKit func didSelectItem(_ indexPath: IndexPath, tabs: Tabs) } -@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol { +@objcMembers open class Tabs: View, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol { + public var tabsModel: TabsModel? { get { return model as? TabsModel } diff --git a/MVMCoreUI/Atomic/Templates/TemplateModel.swift b/MVMCoreUI/Atomic/Templates/TemplateModel.swift index 4f565e85..45c2ed1a 100644 --- a/MVMCoreUI/Atomic/Templates/TemplateModel.swift +++ b/MVMCoreUI/Atomic/Templates/TemplateModel.swift @@ -13,8 +13,7 @@ import Foundation //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - - public class var identifier: String { "" } + open class var identifier: String { "" } public var pageType: String public var template: String { @@ -74,7 +73,7 @@ import Foundation tabBarIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .tabBarIndex) } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(pageType, forKey: .pageType) try container.encode(template, forKey: .template) diff --git a/MVMCoreUI/Containers/Views/Container.swift b/MVMCoreUI/Containers/Views/Container.swift index e3512bab..5b2e83eb 100644 --- a/MVMCoreUI/Containers/Views/Container.swift +++ b/MVMCoreUI/Containers/Views/Container.swift @@ -53,31 +53,28 @@ open class Container: View, ContainerProtocol { open func constrainView(_ view: UIView) { containerHelper.constrainView(view) } -} -// MARK: - MVMCoreViewProtocol -public extension Container { - - override func updateView(_ size: CGFloat) { + // MARK: - MVMCoreViewProtocol + open override func updateView(_ size: CGFloat) { super.updateView(size) (view as? MVMCoreViewProtocol)?.updateView(size) containerHelper.updateViewMargins(self, model: containerModel, size: size) } - + /// Will be called only once. - override func setupView() { + open override func setupView() { super.setupView() isAccessibilityElement = false backgroundColor = .clear } - - func addAndContain(_ view: UIView) { + + open func addAndContain(_ view: UIView) { view.translatesAutoresizingMaskIntoConstraints = false addSubview(view) containerHelper.constrainView(view) self.view = view } - + convenience init(andContain view: UIView) { self.init() addAndContain(view) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index be621811..3fc511f3 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -86,6 +86,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: HeadlineBodyButton.self, for: HeadlineBodyButtonModel.self) ModelRegistry.register(handler: BGImageHeadlineBodyButton.self, for: BGImageHeadlineBodyButtonModel.self) ModelRegistry.register(handler: ThreeHeadlineBodyLink.self, for: ThreeHeadlineBodyLinkModel.self) + ModelRegistry.register(handler: ImageButton.self, for: ImageButtonModel.self) // MARK:- Left Right Molecules ModelRegistry.register(handler: CornerLabels.self, for: CornerLabelsModel.self) diff --git a/Scripts/build_aggregate.sh b/Scripts/build_aggregate.sh new file mode 100755 index 00000000..514d0075 --- /dev/null +++ b/Scripts/build_aggregate.sh @@ -0,0 +1,31 @@ +unset TOOLCHAINS #Xcode 7.3 BUG FIX http://stackoverflow.com/questions/36184930/xcodebuild-7-3-cant-enable-bitcode + +# define output folder environment variable +C_PROJECT_NAME="MVMCoreUI" +PHONE_CONFIGURATION="Release" +SIMULATOR_CONFIGURATION="Debug" +BUILD_DIR=$(xcodebuild -showBuildSettings -project ./MVMCoreUI.xcodeproj | grep -w -o 'BUILD_DIR = .*' | cut -d\ -f3-) +SIMULATOR_LIBRARY_PATH="${BUILD_DIR}/${SIMULATOR_CONFIGURATION}-iphonesimulator/${C_PROJECT_NAME}.framework" +FRAMEWORKS_DIR=$BUILD_DIR/Frameworks +UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/universal + +# Step 1. Build Device and Simulator versions +xcodebuild -scheme "${C_PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${PHONE_CONFIGURATION} -sdk iphoneos -archivePath "${BUILD_DIR}/${PHONE_CONFIGURATION}-iphoneos/${C_PROJECT_NAME}" archive SKIP_INSTALL=false FRAMEWORK_SEARCH_PATHS=$FRAMEWORKS_DIR ALWAYS_SEARCH_USER_PATHS=true + +xcodebuild -target "${C_PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${SIMULATOR_CONFIGURATION} -sdk iphonesimulator BUILD_DIR=$BUILD_DIR FRAMEWORK_SEARCH_PATHS=$FRAMEWORKS_DIR ALWAYS_SEARCH_USER_PATHS=true ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES=true + +mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" + +rm -rf ${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME}.framework +cp -R "${BUILD_DIR}/${PHONE_CONFIGURATION}-iphoneos/${C_PROJECT_NAME}.xcarchive/Products/Library/Frameworks/${C_PROJECT_NAME}.framework" ${UNIVERSAL_OUTPUTFOLDER} + +# Step 2. Create universal binary file using lipo + +lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME}" "${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME}.framework/${C_PROJECT_NAME}" "${SIMULATOR_LIBRARY_PATH}/${C_PROJECT_NAME}" + +mv ${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME} ${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME}.framework/${C_PROJECT_NAME} + +# For Swift framework, Swiftmodule needs to be copied in the universal framework +if [ -d "${SIMULATOR_LIBRARY_PATH}/Modules/${C_PROJECT_NAME}.swiftmodule/" ]; then + cp -a "${SIMULATOR_LIBRARY_PATH}/Modules/${C_PROJECT_NAME}.swiftmodule/" "${UNIVERSAL_OUTPUTFOLDER}/${C_PROJECT_NAME}.framework/Modules/${C_PROJECT_NAME}.swiftmodule/" +fi diff --git a/Scripts/download_dependencies.sh b/Scripts/download_dependencies.sh new file mode 100755 index 00000000..f03a25e8 --- /dev/null +++ b/Scripts/download_dependencies.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +# download_dependencies.sh +# +# Downloads all compiled framework flavors in from Artifactory. +# + +# Create new aggregate builds + +if [ -z $ARTIFACTORY_URL ]; then + ARTIFACTORY_URL="https://oneartifactoryprod.verizon.com/artifactory" +fi + +BUILD_DIR=$(xcodebuild -showBuildSettings -project ./MVMCoreUI.xcodeproj | grep -w -o 'BUILD_DIR = .*' | cut -d\ -f3-) +FRAMEWORKS_DIR=$BUILD_DIR/Frameworks + +if [ ! -d $FRAMEWORKS_DIR ]; then + mkdir $FRAMEWORKS_DIR +fi + +./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/MVMCore.framework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/MVMCore/1.0/MVMCore-1.0-Debug-SNAPSHOT.zip + +./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/MVMAnimationFramework.framework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/MVMAnimationFramework.framework/1.9/MVMAnimationFramework.framework-1.9.zip diff --git a/Scripts/download_framework.sh b/Scripts/download_framework.sh new file mode 100755 index 00000000..9e9e2bb5 --- /dev/null +++ b/Scripts/download_framework.sh @@ -0,0 +1,86 @@ +#!/bin/bash -e + +# upload_framework.sh +# +# Downloads an iOS framework from Artificatory. +# +# An API key from Artifcatory is required in the api_key.private file before uploading. +# + +URL=$1 +LOCALPATH="${2}" +REMOTEPATH="${3}" +LOGFILE=$3 +LOCALDIR=$(dirname "${LOCALPATH}") +LOCALBASE=$(basename "${LOCALPATH}") +NEWFILEPATH="${LOCALDIR}"/$(basename "${REMOTEPATH}") +VERSIONFILE=$LOCALDIR/../Checksums/"${LOCALBASE}".txt + +if [ -z $URL ]; then + echo "The artifactory instance url must be specified as the first argument!" + exit 1 +fi + +#first argument is error message. +exit_with_error () { +echo "Error: $1" +if [ -f "${NEWFILEPATH}" ]; then + rm -rf "${NEWFILEPATH}" 2 +fi +exit 1 +} + +echo "----------------------------------------------------------" +echo "Logs for ${LOCALBASE}" + +echo -e "Local Target: ${LOCALPATH}" +echo -e "Remote Source: ${REMOTEPATH}" + +if [ -z "$LOCALPATH" ]; then + exit_with_error "Missing local path argument" +fi + +if [ -z "$REMOTEPATH" ]; then + exit_with_error "Missing filename path argument" +fi + +#get local and remote checksums for comparison +echo -e "Getting checksums..." +echo -e "URL: ${URL}/api/storage/${REMOTEPATH}" +JSON=$(curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -X GET "${URL}/api/storage/${REMOTEPATH}") +CHECKSUM=$(echo "$JSON" | python -c 'import sys, json; print json.load(sys.stdin)["checksums"]["sha1"]') +if [[ -z "$CHECKSUM" ]]; then + exit_with_error "No Checksum found in json: ${JSON}" +fi +echo "Remote checksum ${CHECKSUM}" +if [[ -f "${VERSIONFILE}" ]]; then + OLDCHECKSUM=$(cat "${VERSIONFILE}") +else + OLDCHECKSUM="none" + mkdir -p $(dirname ${VERSIONFILE}) && touch "$VERSIONFILE" +fi +echo "Local checksum ${OLDCHECKSUM}" + +#get new framework if no original framework, no local checksum, or remote checksum is different from local. +if [ ! -e "${LOCALPATH}" ] || [ -z "$OLDCHECKSUM" ] || [ "$CHECKSUM" != "$OLDCHECKSUM" ]; then + echo "Downloading..." + echo -e "URL: ${URL}/${REMOTEPATH}" + curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -f -X GET "$URL/$REMOTEPATH" --output "${NEWFILEPATH}" + if [ $? -eq 0 ] && [ -e "${NEWFILEPATH}" ]; then + echo "Finished Downloading, begin unzip" + unzip -q -o "${NEWFILEPATH}" -d "${LOCALDIR}" + if [ $? -eq 0 ]; then + echo "Finished unzipping, remove zip" + rm -rf "${NEWFILEPATH}" + echo "Writing new checksum to file" + echo "${CHECKSUM}" > "${VERSIONFILE}" + echo "Successfully downloaded and unzipped archive." + else + exit_with_error "Error unzipping" + fi + else + exit_with_error "Failed to download" + fi +else + echo "Successful, No New Version" +fi diff --git a/Scripts/upload_core_ui_frameworks.sh b/Scripts/upload_core_ui_frameworks.sh new file mode 100755 index 00000000..4a16396c --- /dev/null +++ b/Scripts/upload_core_ui_frameworks.sh @@ -0,0 +1,24 @@ +#!/bin/sh -e + +# upload_core_ui_frameworks.sh +# +# Uploads all compiled framework flavors in MVMCoreUI to Artifactory with the SNAPSHOT classifier. This is to avoid accidently clobbering a release build of a particular version. Remove the classifier in Artificatory to make a release. +# +# Copied from Hedden, Kyle Matthew on 3/2/18. +# + +FRAMEWORK_VERSION=$(cd .. && agvtool vers -terse) +if [ $(git tag --list | grep "v${FRAMEWORK_VERSION}") ]; then + echo This version tag has already been committed! Aborting! + exit 1 +fi + +# Create new aggregate builds + +if [ -z $ARTIFACTORY_URL ]; then + ARTIFACTORY_URL="https://oneartifactoryprod.verizon.com/artifactory" +fi + +# Upload +BUILD_DIR=$(xcodebuild -showBuildSettings -project ../MVMCoreUI.xcodeproj | grep -w -o 'BUILD_DIR = .*' | cut -d\ -f3-) +./upload_framework.sh $ARTIFACTORY_URL "${BUILD_DIR}/universal/MVMCoreUI.framework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/MVMCoreUI/[VER]/MVMCoreUI-[VER]-Debug-SNAPSHOT diff --git a/Scripts/upload_framework.sh b/Scripts/upload_framework.sh new file mode 100755 index 00000000..305a6585 --- /dev/null +++ b/Scripts/upload_framework.sh @@ -0,0 +1,89 @@ +#!/bin/bash -e + +# upload_framework.sh +# +# Uploads an iOS framework to Artificatory given the local path as the first argument and the remote project name in Verizon OneArtifactory for the second argument. +# +# An API key from Artifcatory is required in the api_key.private file before uploading. +# +# The script will replace [VER] in the provided remote path with the version found in the framework bundle. +# +# Copied from Hedden, Kyle Matthew on 3/2/18. +# Copyright © 2018 Verizon. All rights reserved. + +URL=$1 +LOCALPATH=$2 +REMOTEPATH=$3 + +if [ -z $URL ]; then + echo "The artifactory instance url must be specified as the first argument!" + exit 1 +fi + +echo ">>> UPLOAD START <<<" +echo "Local path: ${LOCALPATH}" +echo "Remote path: ${REMOTEPATH}" + +cat "${LOCALPATH}/Info.plist" + +LOCALBASE=$(basename "${LOCALPATH}") +LOCALDIR=$(dirname "${LOCALPATH}") + +# Grab the framework version from the bundled Info.plist. +FRAMEWORKVER=$(/usr/libexec/plistbuddy -c "Print :CFBundleShortVersionString" "${LOCALPATH}/Info.plist") +echo -e "\nFramework version: \t${FRAMEWORKVER}" + +# Replace the [VER] placeholders with the found version. +REMOTEPATH="${REMOTEPATH//\[VER\]/$FRAMEWORKVER}" +echo -e "Resolved path: \t\t${REMOTEPATH}" + +if [ -z $ARTIFACTORY_APIKEY ]; then + # Read the API key from a private file. + read -r APIKEY < "api_key.private" +else + APIKEY=$ARTIFACTORY_APIKEY +fi + +if [ -z $APIKEY ]; then + read -p "Artifactory API Key:" APIKEY + echo $APIKEY >> api_key.private +fi + +echo -e "API Key: \t\t${APIKEY}" + +# Zip the framework & DSYM for uploading. +pushd $LOCALDIR +echo -e "---------\nZipping: \t\t${LOCALBASE}.zip" +zip -r -X "${LOCALBASE}.zip" $LOCALBASE +# Generate framework's SHA-1 checksum. +CHECKSUM=$(shasum -a 1 "${LOCALBASE}.zip" | cut -d " " -f 1) +echo -e "SHA-1 Checksum: \t${CHECKSUM}" +if [ -e ${LOCALBASE}.dSYM ]; then + echo -e "---------\nZipping: \t\t${LOCALBASE}.dSYM.zip" + zip -r -X "${LOCALBASE}.dSYM.zip" $LOCALBASE.dSYM + # Generate its SHA-1 checksum for dsym. + DSYM_CHECKSUM=$(shasum -a 1 "${LOCALBASE}.dSYM.zip" | cut -d " " -f 1) + echo -e "SHA-1 Checksum: \t${DSYM_CHECKSUM}" +fi +popd +mv ${LOCALPATH}.zip . +if [ -e ${LOCALPATH}.dSYM.zip ]; then + mv ${LOCALPATH}.dSYM.zip . +fi + +# Upload framework to Artifactory. +echo -e "---------\nUploading to: \t\t${URL}/${REMOTEPATH}.zip" +curl --header "X-JFrog-Art-Api: ${APIKEY}" --header "X-Checksum-Sha1: ${CHECKSUM}" -X PUT "${URL}/${REMOTEPATH}.zip" -T "${LOCALBASE}.zip" + +# Cleanup. +rm "${LOCALBASE}.zip" + +if [ -e ${LOCALBASE}.dSYM.zip ]; then + # Upload dsym Artifactory. + echo -e "---------\nUploading to: \t\t${URL}/${REMOTEPATH}.dSYM.zip" + curl --header "X-JFrog-Art-Api: ${APIKEY}" --header "X-Checksum-Sha1: ${DSYM_CHECKSUM}" -X PUT "${URL}/${REMOTEPATH}.dSYM.zip" -T "${LOCALBASE}.dSYM.zip" + # Cleanup dsym. + rm ${LOCALBASE}.dSYM.zip +fi + +echo -e "\n\n<<< UPLOAD COMPLETE >>>\n\n"