Replace Towncrier with GitHub releases + labels. (#2966)

* Set up GitHub generated release notes.

* Remove Towncrier from the release script.

* Add changelog failures for Labels with Danger and stop requesting a changelog file.

* Update changelog documentation.
This commit is contained in:
Doug 2024-06-25 12:07:01 +01:00 committed by GitHub
parent 567f22b806
commit 82823c94ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 62 additions and 274 deletions

View File

@ -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.

31
.github/release.yml vendored Normal file
View File

@ -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
- "*"

View File

@ -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

View File

@ -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.")
}

View File

@ -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 %}

View File

@ -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

View File

@ -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

View File

@ -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?

View File

@ -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<String, Array<String>>] 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

View File

@ -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