diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index f11fb9360..b70e6029a 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest name: Danger steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: ~/.danger-swift key: danger-swift-cache-key diff --git a/.github/workflows/release-alpha.yml b/.github/workflows/release-alpha.yml index 92e0310b4..e92b514d5 100644 --- a/.github/workflows/release-alpha.yml +++ b/.github/workflows/release-alpha.yml @@ -33,10 +33,10 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache Ruby gems - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} @@ -52,6 +52,13 @@ jobs: run: | bundle config path vendor/bundle bundle install --jobs 4 --retry 3 + + - uses: actions/setup-python@v3 + with: + python-version: '3.x' + cache: 'pip' + + - run: pip install -r requirements.txt # Import alpha release private signing certificate - name: Import signing certificate @@ -63,7 +70,7 @@ jobs: # Main step # The Ad-hoc release link will be referenced as 'DIAWI_FILE_LINK' # and QR link as 'DIAWI_QR_CODE_LINK' when the Diawi upload succeed - - name: Build Ad-hoc release and send it to Diawi + - name: Build alpha run: bundle exec fastlane alpha env: # Automatically bypass 2FA upgrade if possible on Apple account. @@ -74,10 +81,18 @@ jobs: DIAWI_API_TOKEN: ${{ secrets.DIAWI_API_TOKEN }} GITHUB_PR_NUMBER: ${{ github.event.number }} - - name: Add or update PR comment with Ad-hoc release informations + - name: Read version_changes.md + id: read_changes + uses: juliangruber/read-file-action@v1 + with: + path: ./version_changes.md + + - name: Add release notes and Diawi info uses: NejcZdovc/comment-pr@v1 with: message: | + ${{ steps.read_changes.outputs.content }} + :iphone: Scan the QR code below to install the build for this PR. :lock: This build is for internal testing purpose. Only devices listed in the ad-hoc provisioning profile can install Element Alpha. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c714664d6..e367469a3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,9 +17,9 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }} @@ -29,7 +29,7 @@ jobs: - name: Bundle install run: | bundle config path vendor/bundle - bundle install --jobs 4 --retry 3 + bundle install --jobs 4 --retry 3 - name: Run tests run: bundle exec fastlane tests diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 000000000..e69de29bb diff --git a/changelog.d/_template.md.jinja b/changelog.d/_template.md.jinja new file mode 100644 index 000000000..a0b2dd9ee --- /dev/null +++ b/changelog.d/_template.md.jinja @@ -0,0 +1,58 @@ +{# iOS Repositories #} +{%- set gh_sdk = "https://github.com/matrix-org/matrix-ios-sdk" -%} +{%- set gh_kit = "https://github.com/matrix-org/matrix-ios-kit" -%} +{%- set gh_element = "https://github.com/vector-im/element-ios" -%} + +## {{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }}) +{% for section, _ in sections.items() %} + +{% if sections[section] %} +{% for category, val in definitions.items() if category in sections[section]%} +{{ definitions[category]['name'] }} + +{% if definitions[category]['showcontent'] %} +{% for text, values in sections[section][category].items() %} +{# Build all types of links we can have from our different repositories #} +{%- set links = [] -%} +{%- for value in values %} + {%- if value.startswith("sdk-") %} + {%- set gh_issue = value.replace("sdk-", "") -%} + {{- links.append( "[#%s](%s/issues/%s)" | format(gh_issue, gh_sdk, gh_issue) ) | default("", True) -}} + {%- elif value.startswith("kit-") %} + {%- set gh_issue = value.replace("kit-", "") -%} + {{- links.append( "[#%s](%s/issues/%s)" | format(gh_issue, gh_kit, gh_issue) ) | default("", True) -}} + {%- elif value.startswith("#") %} + {%- set gh_issue = value.replace("#", "") -%} + {{- links.append( "[#%s](%s/issues/%s)" | format(gh_issue, gh_element, gh_issue) ) | default("", True) -}} + {%- elif value.startswith("pr-") %} + {%- set pr = value.replace("pr-", "") -%} + {{- links.append( "[#%s](%s/pull/%s)" | format(pr, gh_element, pr) ) | default("", True) -}} + {%- elif value.startswith("x-nolink-") %} + {{- nil | default("", True) -}} + {% else %} + {{- links.append(value) | default("", True) -}} + {% endif -%} +{% endfor -%} +{% if links|length == 0 %} +- {{ text }} +{% else %} +- {{ text }} ({{ links | join(', ') }}) +{% endif %} +{% endfor %} +{% else %} +- {{ sections[section][category]['']|join(', ') }} + +{% endif %} +{% if sections[section][category]|length == 0 %} +No significant changes. + +{% else %} +{% endif %} + +{% endfor %} +{% else %} +No significant changes. + + +{% endif %} +{% endfor %} \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 9386955aa..0b07a9206 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,4 +1,5 @@ require 'yaml' +require_relative 'changelog' lane :alpha do @@ -24,7 +25,9 @@ lane :alpha do adhoc: true ) - update_app_icon() + version = ENV["GITHUB_PR_NUMBER"] + + update_app_icon(caption_text: "PR #{version}") build_ios_app( clean: true, @@ -39,18 +42,10 @@ lane :alpha do upload_to_diawi() + export_version_changes(version: version) + end -private_lane :config_xcodegen_alpha do - target_file_path = "../ElementX/SupportingFiles/target.yml" - data = YAML.load_file target_file_path - data["targets"]["ElementX"]["settings"]["base"]["PRODUCT_NAME"] = "ElementX PR" - data["targets"]["ElementX"]["settings"]["base"]["PRODUCT_BUNDLE_IDENTIFIER"] = "io.element.elementx.pr" - File.open(target_file_path, 'w') { |f| YAML.dump(data, f) } -end - - - lane :build_and_publish_on_github do ios_adhoc() @@ -102,6 +97,26 @@ lane :tests do end +private_lane :export_version_changes do |options| + Dir.chdir("..") do + Changelog.update_topmost_section(version: options[:version], additional_entries: {}) + changelog = Changelog.extract_first_section + + # Pushing them directly into the $GITHUB_ENV results in errors + # https://trstringer.com/github-actions-multiline-strings/ + # String substitution and here documents failed too + sh("echo '#{changelog}' >> version_changes.md") + end +end + +private_lane :config_xcodegen_alpha do + target_file_path = "../ElementX/SupportingFiles/target.yml" + data = YAML.load_file target_file_path + data["targets"]["ElementX"]["settings"]["base"]["PRODUCT_NAME"] = "ElementX PR" + data["targets"]["ElementX"]["settings"]["base"]["PRODUCT_BUNDLE_IDENTIFIER"] = "io.element.elementx.pr" + File.open(target_file_path, 'w') { |f| YAML.dump(data, f) } +end + desc "Upload IPA to Diawi" private_lane :upload_to_diawi do api_token = ENV["DIAWI_API_TOKEN"] @@ -153,10 +168,9 @@ private_lane :release_to_github do ) end -private_lane :update_app_icon do - pr_number = ENV["GITHUB_PR_NUMBER"] - UI.user_error!("Invalid GitHub PR number.") unless !pr_number.to_s.empty? - caption_text="PR ##{pr_number}" +private_lane :update_app_icon do |options| + caption_text = options[:caption_text] + UI.user_error!("Invalid caption text.") unless !caption_text.to_s.empty? Dir.glob("../ElementX/Resources/Assets.xcassets/AppIcon.appiconset/**/*.png") do |file_name| # Change the icons color diff --git a/fastlane/README.md b/fastlane/README.md index 7a5dd27ab..f6873cd1e 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -53,6 +53,14 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do +### export_release_notes + +```sh +[bundle exec] fastlane export_release_notes +``` + + + ---- This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. diff --git a/fastlane/changelog.rb b/fastlane/changelog.rb new file mode 100644 index 000000000..ff19b43ab --- /dev/null +++ b/fastlane/changelog.rb @@ -0,0 +1,63 @@ +# Copyright 2020 New Vector Ltd - All Rights Reserved +# Unauthorized copying of this file, via any medium is strictly prohibited +# Proprietary and confidential + +# frozen_string_literal: true + +require "tempfile" +require "fileutils" +require "date" + +# Helper methods to handle updates of the Changelog file +# +module Changelog + CHANGES_SEPARATOR_REGEX = /^\#\#\ Changes/.freeze + FILE = "CHANGES.md" + + # Update the topmost section of the changelog to put version+date in title + add entry for dependency updates + # + # @param [String] version The version that we are releasing to use in the new title of the first section + # @param [Hash>] additional_entries + # List of lines/entries to add under the each subsection of the first section + # The keys of the hash are the name of the subsections, without trailing`:`, e.g. "Improvements". + # The values are the list of lines to add to that subsection + # (the ` * ` bullet point will be added automatically for each line) + # + def self.update_topmost_section(version:, additional_entries:) + + # Create temporary towncrier changelog entries for additional entries + # Use a low index to make them appear first + # Those additional entries are basically dependency updates + entry_count = 0 + additional_entries.each do |subsection, entries| + entries.each do |entry| + file = "changelog.d/x-nolink-#{entry_count}.#{subsection}" + File.write(file, "#{entry}") + Git.add!(files: file) + Git.commit!(message: "changelog.d: #{entry}", add_all: true) + entry_count += 1 + end + end + + # Let towncrier update the change + system("towncrier", "build", "--version", "#{version}", "--yes") + end + + # Returns the first section of the Changelog, corresponding to the changes in the latest version + # + def self.extract_first_section + lines = [] + File.open(FILE, "r") do |file| + section_index = 0 + file.each_line do |line| + is_separator_line = (line.chomp =~ CHANGES_SEPARATOR_REGEX) + section_index += 1 if is_separator_line + break if section_index >= 2 + + lines.append(line) if section_index == 1 + end + end + lines[0..-2].join # Remove last line (title of section 2) + end + +end diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..d2e58a2c3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +###### Requirements without Version Specifiers ###### + +towncrier \ No newline at end of file diff --git a/towncrier.toml b/towncrier.toml new file mode 100644 index 000000000..689728cc2 --- /dev/null +++ b/towncrier.toml @@ -0,0 +1,50 @@ +[tool.towncrier] +name = "Changes in" +filename = "CHANGES.md" +directory = "changelog.d" +template = "changelog.d/_template.md.jinja" + +[[tool.towncrier.type]] + directory = "feature" + name = "✨ Features" + showcontent = true + +[[tool.towncrier.type]] + directory = "change" + name = "🙌 Improvements" + showcontent = true + +[[tool.towncrier.type]] + directory = "bugfix" + name = "🐛 Bugfixes" + showcontent = true + +[[tool.towncrier.type]] + directory = "api" + name = "⚠️ API Changes" + showcontent = true + +[[tool.towncrier.type]] + directory = "i18n" + name = "🗣 Translations" + showcontent = true + +[[tool.towncrier.type]] + directory = "build" + name = "🧱 Build" + showcontent = true + +[[tool.towncrier.type]] + directory = "doc" + name = "📄 Documentation" + showcontent = true + +[[tool.towncrier.type]] + directory = "wip" + name = "🚧 In development 🚧" + showcontent = true + +[[tool.towncrier.type]] + directory = "misc" + name = "Others" + showcontent = true