diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4c60a17b7..676342753 100755 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -30,7 +30,7 @@ If you are not sure about the likelihood of a change you propose to be accepted, Templates are available when you want to contribute: * [Issues](https://github.com/SRGSSR/playsrg-apple/issues): Please follow our issue template. You can omit information which does not make sense but, in general, the more details you can provide, the better. This ensures we can quickly reproduce the problem you are facing, increasing the likelihood we can fix it. -* [Pull requests](https://github.com/SRGSSR/playsrg-apple/pulls): Please follow our code conventions and [workflows](WORKFLOWS.md), test your code well, and write unit tests when this makes sense. We will review your work and, if successful, merge it back into the main development branch. +* [Pull requests](https://github.com/SRGSSR/playsrg-apple/pulls): Please follow our [code conventions](#code-conventions) and [workflows](WORKFLOWS.md), test your code well, and write unit tests when this makes sense. We will review your work and, if successful, merge it back into the main development branch. ## Code conventions diff --git a/docs/README.md b/docs/README.md index c22be664a..c95bbe667 100755 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,21 @@ ![SRG Media Player logo](README-images/logo.png) +- [About](#about) +- [Features](#features) +- [Compatibility](#compatibility) +- [Required tools](#required-tools) +- [Building the project](#building-the-project) + - [Project setup](#project-setup) + - [Private settings](#private-settings) + - [Running the project](#running-the-project) + - [Quality checks](#quality-checks) + - [Git hooks installation](#git-hooks-installation) + - [Licenses for libraries](#licenses-for-libraries) + - [Translations](#translations) +- [Contributing](#contributing) +- [Releasing binaries](#releasing-binaries) +- [Documentations](#documentations) + ## About Play SRG is the [SRG SSR (Swiss Broadcasting Corporation)](https://www.srgssr.ch/en/who-we-are/organisation/) audio and video platform, provided as a distinct service for each of its business units ([RSI](https://www.rsi.ch), [RTR](https://www.rtr.ch), [RTS](https://www.rts.ch), [SRF](https://www.srf.ch) and [SWI](https://www.swissinfo.ch)). This repository contains the source code of the Play SRG applications for iOS and tvOS. @@ -113,18 +129,6 @@ make check-quality This ensures that Swift files, and scripts are conform to common best practices. -### Licenses for libraries used in the project - -In the iOS application settings, licenses of libraries used in the project can be consulted. To build the list, running an iOS target requires [LicensePlist](https://github.com/mono0926/LicensePlist). - -``` -brew install licenseplist -``` - -### SRGSSR project - -Some links to [internal Jira SRGSSR instance](https://srgssr-ch.atlassian.net) can be found in commit messages, branch names or pull request titles. - ### Git hooks installation Project git hooks can be installed to help quality checks and commit messages for internal SRGSSR project. Install them by running the following command: @@ -133,13 +137,17 @@ Project git hooks can be installed to help quality checks and commit messages fo make git-hook-install ``` -## Contributing +### Licenses for libraries -If you want to contribute to the project as an external contributor, have a look at our [contributing guide](CONTRIBUTING.md). +In the iOS application settings, licenses of libraries used in the project can be consulted. To build the list, running an iOS target requires [LicensePlist](https://github.com/mono0926/LicensePlist). -## Translations +``` +brew install licenseplist +``` -Translation tool is [crowdin.com](https://crowdin.com/project/play-srg). The following scripts need [Crowdin CLI](https://crowdin.github.io/crowdin-cli/). +### Translations + +Translation tool is [crowdin.com](https://crowdin.com/project/play-srg). The following scripts need [Crowdin CLI](https://crowdin.github.io/crowdin-cli/) and a private token. - Review new source translation files in `Translations` folder: @@ -159,6 +167,10 @@ Translation tool is [crowdin.com](https://crowdin.com/project/play-srg). The fol make pull-translations ``` +## Contributing + +If you want to contribute to the project as an external contributor, have a look at our [contributing guide](CONTRIBUTING.md) and our [workflows](WORKFLOWS.md). + ## Releasing binaries The proprietary project uses [fastlane](https://fastlane.tools/) to release binaries either for internal purposes or for the App Store to release binaries. @@ -169,12 +181,12 @@ A [github page](https://srgssr.github.io/playsrg-apple/) with release notes page See [release checklist](RELEASE_CHECKLIST.md) for App Store release details. -## Specifications +## Documentations Follow the links below for feature specifications and technical details: -* [Configuration files](CONFIGURATION_FILES.md) -* [Remote configuration](REMOTE_CONFIGURATION.md) * [Custom URL and Universal Link Support](CUSTOM_URLS_AND_UNIVERSAL_LINKS.md) -* [Push notifications](PUSH_NOTIFICATIONSSS.md) +* [Push notifications](PUSH_NOTIFICATIONS.md) +* [Remote configuration](REMOTE_CONFIGURATION.md) +* [Configuration files](CONFIGURATION_FILES.md) * [Github environments and deployments](GITHUB_ENVIRONMENTS_AND_DEPLOYMENTS.md) \ No newline at end of file diff --git a/docs/WORKFLOWS.md b/docs/WORKFLOWS.md index b15860be2..9a36f8da7 100755 --- a/docs/WORKFLOWS.md +++ b/docs/WORKFLOWS.md @@ -1,11 +1,26 @@ -# Workflows +# Workflows The project implements some workflows. It a mix of: -- Fastlane scripts (needs `make ruby-setup` to setup Ruby). -- Bash scripts (with `make` commands). +- Fastlane scripts (mostly running on an [on premise TeamCity instance](https://playcity.eu.ngrok.io/project/playsrgios) but can be run locally as well). +- Bash scripts (locally with `make` commands). - Github actions (running on [github.com](https://github.com/SRGSSR/playsrg-apple)). +### Table of Contents +- [Start a feature or a bug fix](#start-a-feature-or-a-bug-fix) + - [Start from an internal Jira ticket](#start-from-an-internal-jira-ticket) + - [Start from a public Github issue](#start-from-a-public-github-issue) +- [Build and distribute Private Nightlies](#build-and-distribute-private-nightlies) +- [Submit to review a feature or a bug fix](#submit-to-review-a-feature-or-a-bug-fix) +- [Build and distribute Private Betas](#build-and-distribute-private-betas) +- [Build and distribute Public Betas and AppStore Builds](#build-and-distribute-public-betas-and-appstore-builds) +- [Prepare an App Store release](#prepare-an-app-store-release) +- [Update the App Store screenshots](#update-the-app-store-screenshots) +- [Submit an App Store release for review](#submit-an-app-store-release-for-review) +- [Follow App Store release status](#follow-app-store-release-status) +- [Release notes on Github pages](#release-notes-on-github-pages) +- [Bump platform version after a release](#bump-platform-version-after-a-release) + # Start a feature or a bug fix 🙏 Please first run one time on the Mac, `make git-hook-install`, so that the `pre-commit` linter and Jira `commit-msg` are installed. @@ -250,14 +265,15 @@ On [crowdin.com PlaySRG project](https://crowdin.com/project/play-srg/sources/fi 5. On PlayCity CI select the project: - **[Play SRG iOS AppStore releases](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgIOSAppStoreReleases)**: `fastlane ios iOSPrepareAppStoreReleases` - **[Play SRG tvOS AppStore releases](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgTvOSAppStoreReleases)**: `fastlane ios tvOSPrepareAppStoreReleases` -6. Select the commit with the tag. -7. Run the project. The script: +6. "Run" the project to open the dialog view. +7. In the *Parameters* tab, set the `tag_version` parameter (`X.Y.Z-N`) to use, if the version on `main` branch is not the expected one (**should not be the case**). +8. "Run build" from the dialog view. The script: - Creates a new App Store release on App Store Connect with the current version if not already existing. - Sets the translated what's new for this version. - Updates the what's new App Store release notes with the translated release notes from crowdin.com. - - Does basic checks with [Fastlane precheck](https://docs.fastlane.tools/actions/precheck/). + - Does some basic metadata checks with [Fastlane precheck](https://docs.fastlane.tools/actions/precheck/). - No submission to Apple review is done for now. -8. We can follow Apple release status and what's new release notes locally with `make appstore-status`. +9. We can follow Apple release status and what's new release notes locally with `make appstore-status`. ℹ️ The project can be rerun to update the translated App Store release notes if needed. @@ -328,16 +344,65 @@ Let's submit the App Store release for review: 2. On PlayCity CI select the project: - **[Play SRG iOS AppStore releases](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgIOSAppStoreReleases)**: `fastlane ios iOSPrepareAppStoreReleases submit_for_review:true` - **[Play SRG tvOS AppStore releases](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgTvOSAppStoreReleases)**: `fastlane ios tvOSPrepareAppStoreReleases submit_for_review:true` -3. Select the commit with the tag. -4. Check the `submit_for_review` parameter. -5. Run the project. The script: +3. "Run" the project to open the dialog view. +4. In the *Parameters* tab, check the `submit_for_review` parameter. +5. In the *Parameters* tab, set the `tag_version` parameter (`X.Y.Z-N`) to use, if the version and build number on `main` branch are not the expected one (**should be the case**). +6. "Run build" from the dialog view. The script: - Creates a new App Store release on App Store Connect with the current version if not already existing. - Sets the translated what's new for this version. - Updates the what's new App Store release notes with the translated release notes from crowdin.com. - - Does basic checks with [Fastlane precheck](https://docs.fastlane.tools/actions/precheck/). - - The latest build related to the version is submitted to Apple review (highest build number). + - Does some basic metadata checks with [Fastlane precheck](https://docs.fastlane.tools/actions/precheck/). + - The build related to the tag version is submitted to Apple review (build number from the `tag_version` parameter in the dialog view). - 🚀 Submission to Apple review is done this time. -6. We can follow Apple release status and what's new release notes locally with `make appstore-status`. + - *Automatically release this version* is set, to automatically release it after it has been approved by Apple App Review. +7. We can follow Apple release status and what's new release notes locally with `make appstore-status`. + +# Follow App Store release status + +Now, it's in Apple App Review team hands. Any Apple Ids linked to applications on App Store Connect will receive by email status update. + +Locally, on a Mac, running `make appstore-status` give the current status for all Play SRG applications on App Store Connect. + +ℹ️ The script is also scheduled to run on CI automatically. + +1. On PlayCity CI select the project: + - **[Play SRG AppStore status](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgAppStoreStatus)**: `fastlane ios appStoreAppStatus github_deployments:true publish_release_notes:true` +2. Select the `main` branch (should be already selected). +3. Run the project. The script: + - Gets AppStore live versions. + - Gets lastest AppStore versions (can be the new submitted one or the live one). + - checkes that the lastest AppStore version is different as the live version. Then the script: + - Updates Github production deployment according to the last AppStore release state. + - Displays in the console, live and latests versions, build number , current release state, and what's new. + - Runs `fastlane ios publishReleaseNotes` if a Github production deployment state has switched to `success`. (see [Release notes on Github pages](#release-notes-on-github-pages)) + +```mermaid +--- +title: Follow App Store release status +--- +sequenceDiagram + participant Fastlane + participant ASC as App Store Connect + Fastlane->>ASC: Ask live version + activate Fastlane + activate ASC + ASC-->>Fastlane: Get live version + deactivate ASC + Fastlane->>Github: Ask production deployment state + activate Github + Github-->>Fastlane: Get production deployment state + deactivate Github + Fastlane->>Github: Update production deployment state if needed + Fastlane->>ASC: Ask latest version + activate ASC + ASC-->>Fastlane: Get latest version + deactivate ASC + Fastlane->>Github: Update production deployment state if needed + Fastlane->>Github: Push new gh-page with release notes if needed + deactivate Fastlane +``` + +ℹ️ To learn more about Github deployments, see [Github environments and deployments](GITHUB_ENVIRONMENTS_AND_DEPLOYMENTS.md). # Release notes on Github pages @@ -346,13 +411,15 @@ It downloads a html file to display release notes. The html pages are published Publish release notes on Github pages with correct released status (App Store and TestFlight release notes): -ℹ️ The script is scheduled to run on CI after a private or public beta build success. +ℹ️ The script is scheduled to run on CI after a private or public beta build success, also when an AppStore release is found with the [Play SRG AppStore status](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgAppStoreStatus) check. 1. On PlayCity CI select the project: - **[Play SRG Publish release notes](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgPublishReleaseNotes)**: `fastlane ios publishReleaseNotes` 2. Run the project. The script: - - Does the `gh-pages` branch update automatically. - - Can be from any branch. No dependency with versions or build numbers. + - Gets translated whats's new from Crowdin. + - Gets live version from App Store Connect. + - Force pushes updated pages to the `gh-pages` branch. + - Can be run from any branch. No dependency with versions or build numbers. The update can be done manually (not recommended), without keeping the commits history on the `gh-pages` branch: @@ -364,14 +431,34 @@ The update can be done manually (not recommended), without keeping the commits h - Switch back to another branch. - Remove local `gh-pages` branch (recommended if the fastlane script needs to run later). -# Bump versions +```mermaid +--- +title: Release notes on Github pages +--- +sequenceDiagram + Fastlane->>Crowdin: Ask what's new translated csv files + activate Fastlane + activate Crowdin + Crowdin-->>Fastlane: Get what's new translated csv files + deactivate Crowdin + participant ASC as App Store Connect + Fastlane->>ASC: Ask live version + activate Fastlane + activate ASC + ASC-->>Fastlane: Get live version + deactivate ASC + Fastlane->>Github: Publish new gh-pages + deactivate Fastlane +``` + +# Bump platform version after a release When a release is published on the App Store, the version number (`X.Y.Z`) needs to be bumped for the next release. ℹ️ The script is scheduled to run on CI automatically. 1. On PlayCity CI select the project: - - **[Play SRG After AppStore validation](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgAfterAppStoreValidation)**: `fastlane ios afterAppStoreValidation` + - **[Play SRG After AppStore release](https://playcity.eu.ngrok.io/buildConfiguration/playsrgios_PlaySrgAfterAppStoreRelease)**: `fastlane ios afterAppStoreRelease` 2. Select the `main` branch (should be already selected). 3. Run the project. The script: - Get AppStore live versions. @@ -379,7 +466,6 @@ When a release is published on the App Store, the version number (`X.Y.Z`) needs - Bumps the patch number of version number (`X.Y.Z`) on the repository. - Commits the version bump with message "Bump version to `X.Y.Z+1`". - Pushes the commit to the repository. - - Runs `fastlane ios publishReleaseNotes` if a marketing version as been bumped. ```mermaid --- diff --git a/fastlane/Fastfile b/fastlane/Fastfile index a3d329eac..996800a7e 100755 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -20,7 +20,7 @@ default_platform :ios platform :ios do before_all do |lane, options| platform = platform(lane) - tag_version = options[:tag_version] || tag_version(platform) + tag_version = tag_version_from_options(options) || tag_version(platform) branch_name = git_branch_name notify_version_to_ci(platform, tag_version, branch_name) if notify_ci_condition(lane) @@ -215,9 +215,11 @@ platform :ios do # App Store App status - desc 'Get AppStore App status for iOS and tvOS. Optional `github_deployments` (boolean) parameter.' + desc 'Get AppStore App status for iOS and tvOS. Optional `github_deployments` (boolean) and `publish_release_notes` (boolean) parameters.' lane :appStoreAppStatus do |options| github_deployments = options[:github_deployments] || false + publish_release_notes = options[:publish_release_notes] || false + new_live_version_found = false UI.message '-----' business_units.map do |business_unit| @@ -234,7 +236,10 @@ platform :ios do UI.success "Play #{business_unit} #{platform} live version #{live_version.version_string} (#{live_version.build.version}) is #{live_version.app_store_state}." if live_version UI.important "Play #{business_unit} #{platform} has no live version." unless live_version - appstore_github_deployment(business_unit, platform, live_version) if github_deployments + if github_deployments + state = appstore_github_deployment(business_unit, platform, live_version) + new_live_version_found ||= state == 'success' if state + end latest_version = spaceship_app_latest_known_version(platform, app) if !latest_version || latest_version.version_string == live_version.version_string @@ -251,6 +256,8 @@ platform :ios do end end UI.message '-----' + + run_publish_release_notes(new_live_version_found) if publish_release_notes end desc 'Get AppStore TestFlight App status for iOS and tvOS, lastest version' @@ -354,12 +361,12 @@ platform :ios do UI.success 'Play release notes pushed on Github pages. ✅' end - # After AppStore validation + # After AppStore release - desc 'After AppStore validation: Bumps marketing version and pushes if one AppStore live version is same as the current marketing version.' - lane :afterAppStoreValidation do + desc 'After an AppStore release: Bumps marketing version and pushes if one AppStore live version is same as the current marketing version.' + lane :afterAppStoreRelease do unless git_branch_name == github_main_branch - UI.user_error! 'After AppStore validation must runs on \'main\' branch.' + UI.user_error! 'After AppStore release must be run on \'main\' branch.' end appstore_live_versions = { 'iOS' => [], 'tvOS' => [] } @@ -384,15 +391,10 @@ platform :ios do end UI.message '-----' - publish_release_notes = false - # Bump marketing version if needed appstore_live_versions.each do |platform, appstore_versions| - bumped = bump_marketing_version_flow(platform, appstore_versions) - publish_release_notes ||= bumped + bump_marketing_version_flow(platform, appstore_versions) end - - sh 'bundle exec fastlane ios publishReleaseNotes' if publish_release_notes end # Individual iOS screenshots @@ -785,7 +787,7 @@ platform :ios do desc 'Distributes the App Store build on App Store Connect with the current build number to TestFlight groups.' private_lane :testflight_distribute_appstore_build do |options| platform = options[:platform] || 'iOS' - tag_version = options[:tag_version] || tag_version(platform) + tag_version = tag_version_from_options(options) || tag_version(platform) scheme = application_scheme(platform, options[:bu]) public_beta_distribution = options[:public_beta_distribution] || true @@ -1107,6 +1109,12 @@ def itc_team_id_index(itc_team_id) itc_team_ids.index(itc_team_id) end +def tag_version_from_options(options) + # CI can set an empty string + tag_version = options[:tag_version] || '' + tag_version unless tag_version.empty? +end + # Returns current tag version def tag_version(platform) "#{xcode_marketing_version(platform)}-#{xcode_build_number}" @@ -1146,8 +1154,7 @@ def what_s_new_for_beta(platform, tag_version) tag_version ||= tag_version(platform) json = what_s_new_for_beta_json(platform) - what_s_new = json[tag_version] - what_s_new ||= '' + what_s_new = json[tag_version] || '' if !what_s_new.empty? && !build_name(git_branch_name).empty? && !what_s_new.downcase.include?('branch') what_s_new = "This build is from a test branch.\n\n#{what_s_new}" @@ -1860,6 +1867,7 @@ def check_appstore_github_deployment(lane_name, business_unit, app_version, tag_ state = github_deployment_state_from_app_version(app_version) update_github_appstore_deployment(lane_name, business_unit, tag_deployment, state) + state end def get_github_appstore_tag_deployment(tag, lane_name, business_unit) @@ -2100,9 +2108,14 @@ end def prepare_appstore_release(platform, business_unit, options) platform ||= 'iOS' - tag_version = options[:tag_version] || tag_version(platform) + tag_version = tag_version_from_options(options) || tag_version(platform) submit_for_review = options[:submit_for_review] || false + tag = srg_tag_from_tag_version(platform, tag_version) + if submit_for_review && !git_tag_exists(tag:, remote: true) + UI.user_error! "Tag version #{tag_version} for #{platform} does not exist. Please set one which is related to existing AppStore build." + end + return unless can_run_deliver(business_unit, platform) metadata_path = appstore_release_metadata_path(platform, business_unit, tag_version) @@ -2225,7 +2238,8 @@ def crowdin_language(business_unit) end def pull_translations_lane_condition(lane) - lane.to_s.downcase.include? 'release' + included_lanes = ['prepareappstorerelease', 'releasenotes'] + included_lanes.one? { |i| lane.to_s.downcase.include? i } end def skip_pull_translations @@ -2551,6 +2565,14 @@ def spaceship_app_external_groups_state(beta_detail, group_builds, build_id) { state:, message: } end +def run_publish_release_notes(need_update) + UI.message 'Release notes: no new AppStore releases have been found.' + return unless need_update + + UI.command_output 'Release notes: new AppStore releases have been found. Update github page.' + sh 'bundle exec fastlane ios publishReleaseNotes' +end + def copy_static_github_pages_files(output_directory) source_directory = 'fastlane/gh-pages' copy_static_github_pages_files_from_to(source_directory, output_directory) diff --git a/fastlane/README.md b/fastlane/README.md index 0eeef7b25..80dcd3b7b 100755 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -141,7 +141,7 @@ Prepare AppStore tvOS releases on App Store Connect with the current version and [bundle exec] fastlane ios appStoreAppStatus ``` -Get AppStore App status for iOS and tvOS. Optional `github_deployments` (boolean) parameter. +Get AppStore App status for iOS and tvOS. Optional `github_deployments` (boolean) and `publish_release_notes` (boolean) parameters. ### ios appStoreTestFlightAppStatus @@ -159,13 +159,13 @@ Get AppStore TestFlight App status for iOS and tvOS, lastest version Publish release notes for iOS and tvOS on Github pages -### ios afterAppStoreValidation +### ios afterAppStoreRelease ```sh -[bundle exec] fastlane ios afterAppStoreValidation +[bundle exec] fastlane ios afterAppStoreRelease ``` -After AppStore validation: Bumps marketing version and pushes if one AppStore live version is same as the current marketing version. +After an AppStore release: Bumps marketing version and pushes if one AppStore live version is same as the current marketing version. ### ios iOSrsiScreenshots