diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index cfdff383d..398b38d1f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,8 @@ ### Pull Request Checklist -- [ ] I read the [contributing guide](https://github.com/element-hq/element-ios/blob/develop/CONTRIBUTING.md) -- [ ] Pull request contains a [changelog file](https://github.com/matrix-org/matrix-ios-sdk/blob/develop/CONTRIBUTING.md#changelog) in ./changelog.d -- [ ] Pull request includes a [sign off](https://github.com/matrix-org/matrix-ios-sdk/blob/develop/CONTRIBUTING.md#sign-off) +- [ ] I read the [contributing guide](https://github.com/element-hq/element-ios/blob/develop/CONTRIBUTING.md). +- [ ] Pull request contains a [changelog label](https://github.com/element-hq/element-x-ios/blob/develop/CONTRIBUTING.md#changelog). +- [ ] Pull request includes a [sign off](https://github.com/matrix-org/matrix-ios-sdk/blob/develop/CONTRIBUTING.md#sign-off). **UI changes have been tested with:** - [ ] iPhone and iPad simulators in portrait and landscape orientations. diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..e93e4c076 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,31 @@ +changelog: + categories: + - title: ✨ Features + labels: + - pr-feature + - title: πŸ™Œ Improvements + labels: + - pr-change + - title: πŸ› Bugfixes + labels: + - pr-bugfix + - title: ⚠️ API Changes + labels: + - pr-api + - title: πŸ—£ Translations + labels: + - pr-i18n + - title: 🧱 Build + labels: + - pr-build + - title: πŸ“„ Documentation + labels: + - pr-doc + - title: 🚧 In development 🚧 + labels: + - pr-wip + + - title: Others + labels: + - pr-misc + - "*" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 10da13065..4544b8341 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,55 +99,7 @@ New screen flows are currently using the MVVM-Coordinator pattern. Please refer ## Changelog -All changes, even minor ones, need a corresponding changelog / newsfragment -entry. These are managed by [Towncrier](https://github.com/twisted/towncrier). - -To create a changelog entry, make a new file in the `changelog.d` directory -named in the format of `ElementXiOSIssueNumber.type`. The type can be one of the -following: - -- `feature` for a new feature -- `change` for updates to an existing feature -- `bugfix` for bug fix -- `api` for an api break -- `i18n` for translations -- `build` for changes related to build, tools, CI/CD -- `doc` for updates to the documentation -- `wip` for anything that isn't ready to ship and will be enabled at a later date -- `misc` for other changes - -This file will become part of our [changelog](CHANGES.md) at the next -release, so the content of the file should be a short description of your -change in the same style as the rest of the changelog. The file must only -contain one line. It can contain Markdown formatting. It should start with the -area of the change (screen, module, ...) and end with a full stop (.) or an -exclamation mark (!) for consistency. - -Adding credits to the changelog is encouraged, we value your -contributions and would like to have you shouted out in the release notes! - -For example, a fix for an issue #1234 would have its changelog entry in -`changelog.d/1234.bugfix`, and contain content like: - -> Voice Messages: Fix a crash when sending a voice message. Contributed by -> Jane Matrix. - -If there are multiple pull requests involved in a single bugfix/feature/etc, -then the content for each `changelog.d` file should be the same. Towncrier will -merge the matching files together into a single changelog entry when we come to -release. - -There are exceptions on the `ElementXiOSIssueNumber.type` entry format. Even if -it is not encouraged, you can use: - -- `pr-[PRNumber].type` for a PR with no related issue -- `x-nolink-[AnyNumber].type` for a PR with a change entry that will not have a link automatically appended. It must be used for internal project update only. `AnyNumber` should be a value that does not clash with existing files. - -To preview the changelog for pending changelog entries, use: - -```bash -$ towncrier build --draft --version 1.2.3 -``` +Our [changelog](CHANGES.md) is automatically generated by GitHub, based on the PR title that you use when opening the issue. The changelog can be categorised by applying on of the [`pr-` labels](https://github.com/element-hq/element-x-ios/labels?q=pr-) to your PR. The mapping of Label β†’ Section can be found in the [release.yml](.github/release.yml) file. The contribution will be automatically credited to your GitHub username. ## Coding style diff --git a/Dangerfile.swift b/Dangerfile.swift index 0e0b181b2..43508205e 100644 --- a/Dangerfile.swift +++ b/Dangerfile.swift @@ -5,6 +5,9 @@ SwiftLint.lint(inline: true) let danger = Danger() +// All of the new and modified files together. +let editedFiles = danger.git.modifiedFiles + danger.git.createdFiles + // Warn when there is a big PR if (danger.github.pullRequest.additions ?? 0) > 1000 { warn("This pull request seems relatively large. Please consider splitting it into multiple smaller ones.") @@ -15,14 +18,6 @@ if danger.github.pullRequest.body?.isEmpty ?? true { warn("Please provide a description for this PR.") } -// Request a changelog for each app change -let editedFiles = danger.git.modifiedFiles + danger.git.createdFiles -let changelogFiles = editedFiles.filter { $0.hasPrefix("changelog.d/") } - -if editedFiles.count > 0, changelogFiles.isEmpty { - warn("Please add a changelog.") -} - // Check for a ticket number if let ticketNumberRegex = try? NSRegularExpression(pattern: "#\\d+") { let missingTicketNumber = !danger.git.commits.filter { @@ -84,3 +79,11 @@ let hasPngs = !editedFiles.filter { $0.lowercased().contains(".xcassets") && $0. if hasPngs { warn("You seem to have made changes to some resource images. Please consider using an SVG or PDF.") } + +if danger.github.pullRequest.title.hasSuffix("…") { + fail("Please provide a complete title that can be used as a changelog entry.") +} + +if danger.github.issue.labels.filter({ $0.name.hasPrefix("pr-") }).count != 1 { + fail("Please add a `pr-` label to categorise the changelog entry.") +} diff --git a/changelog.d/_template.md.jinja b/changelog.d/_template.md.jinja deleted file mode 100644 index d9eb42302..000000000 --- a/changelog.d/_template.md.jinja +++ /dev/null @@ -1,54 +0,0 @@ -{# iOS Repositories #} -{%- set gh_sdk = "https://github.com/matrix-org/matrix-rust-sdk" -%} -{%- set gh_element = "https://github.com/element-hq/element-x-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("#") %} - {%- 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/ci_scripts/ci_common.sh b/ci_scripts/ci_common.sh index f16001fe8..c82c0271d 100755 --- a/ci_scripts/ci_common.sh +++ b/ci_scripts/ci_common.sh @@ -38,10 +38,6 @@ install_xcode_cloud_brew_dependencies () { fi } -install_xcode_cloud_python_dependencies () { - pip3 install towncrier # Install towncrier for generating changelogs -} - setup_github_actions_environment() { unset HOMEBREW_NO_INSTALL_FROM_API export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 diff --git a/ci_scripts/ci_post_xcodebuild.sh b/ci_scripts/ci_post_xcodebuild.sh index 1775750a1..973af5961 100755 --- a/ci_scripts/ci_post_xcodebuild.sh +++ b/ci_scripts/ci_post_xcodebuild.sh @@ -11,8 +11,6 @@ bundle exec fastlane upload_dsyms_to_sentry dsym_path:"$CI_ARCHIVE_PATH/dSYMs" generate_what_to_test_notes if [ "$CI_WORKFLOW" = "Release" ]; then - install_xcode_cloud_python_dependencies - bundle exec fastlane release_to_github bundle exec fastlane prepare_next_release elif [ "$CI_WORKFLOW" = "Nightly" ]; then diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 3821d9392..b24579d0a 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,6 +1,5 @@ require 'yaml' require 'semantic' -require_relative 'changelog' before_all do xcversion(version: "15.2") @@ -208,35 +207,30 @@ lane :release_to_github do api_token = ENV["GITHUB_TOKEN"] UI.user_error!("Invalid GitHub API token.") unless !api_token.to_s.empty? - # Get the Diawi link from Diawi action shared value - diawi_link = lane_context[SharedValues::UPLOADED_FILE_LINK_TO_DIAWI] - release_version = get_version_number(target: "ElementX") - changes = export_version_changes(version: release_version) - - description = "" - if diawi_link.nil? - description = "#{changes}" - else - # Generate the Diawi QR code file link - diawi_app_id = URI(diawi_link).path.split('/').last - diawi_qr_code_link = "https://www.diawi.com/qrcode/link/#{diawi_app_id}" - - "[iOS AdHoc Release - Diawi Link](#{diawi_link}) - ![QR code](#{diawi_qr_code_link}) - #{changes}" - end - github_release = set_github_release( repository_name: "element-hq/element-x-ios", api_token: api_token, name: release_version, tag_name: release_version, - is_generate_release_notes: false, - description: description + is_generate_release_notes: true, ) - + + release_date = Date.today.strftime("%Y-%m-%d") + generated_notes = github_release["body"].gsub(//, '').gsub("### ", "\n").gsub("## ", "### ") + UI.user_error!("The generated release notes are missing!") unless !generated_notes.to_s.empty? + + # Prepend the new release notes to the CHANGES.md file + changes_file = "../CHANGES.md" + File.open(changes_file, "r+") do |file| + content = file.read + file.rewind + file.write("## Changes in #{release_version} (#{release_date})#{generated_notes}\n\n#{content}") + end + + # The changelog will be committed when prepare_next_release is called. + sh("git add #{changes_file}") end lane :prepare_next_release do @@ -366,13 +360,6 @@ private_lane :bump_build_number do increment_build_number(build_number: build_number) end -private_lane :export_version_changes do |options| - Dir.chdir("..") do - Changelog.update_topmost_section(version: options[:version], additional_entries: {}) - Changelog.extract_first_section - end -end - private_lane :update_app_icon do |options| caption_text = options[:caption_text] UI.user_error!("Invalid caption text.") unless !caption_text.to_s.empty? diff --git a/fastlane/changelog.rb b/fastlane/changelog.rb deleted file mode 100644 index a8cad42ff..000000000 --- a/fastlane/changelog.rb +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright 2020 New Vector Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# 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/towncrier.toml b/towncrier.toml deleted file mode 100644 index 689728cc2..000000000 --- a/towncrier.toml +++ /dev/null @@ -1,50 +0,0 @@ -[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