Add changelog generation (#761)

* WIP Release notes generation and templates

* WIP Add new sections to the template

* WIP renaming and wip

* Fix runtime template

* Add doc, NO_CACHE and tweaking of the templates

* Renaming cl into cumulus to make room for the polkadot and substrate

* Fetch data from Substrate and Polkadot

* WIP convert bash script to ruby

* Convert to Ruby

* Fix host function delection

* Extract priority to a macro

* Fix misc changes

* Draft release workflow

* Fix runtime dir

* Add ENV to ignore runtimes

* Install tooling separately

* WIP troubleshooting - remove sudo

* Minor formatting fixes

* Fix workflow

* Add missing dep

* Linting

* Fix changelog script

* Add missing tera install

* Use absolute paths

* Fix path + cleanup

* Fix changelog generation

* Add missing pre-release ENV

* Fix rust version ENV

* Fix release notes path

* Fix output

* Fix runtime_dir for cumulus

* Fix ENV substitutions

* Fix styling

* Debugging

* Styling

* Fix call to fetch the runtime version

* Cleanup and doc

* Delete sample .env

* Update scripts/changelog/templates/change.md.tera

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* Change XCM emoji marker for a ✉️

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
This commit is contained in:
Chevdor
2021-11-19 17:30:05 +01:00
committed by GitHub
parent 69f030f81c
commit e4e8d4fb83
28 changed files with 897 additions and 15 deletions
+207
View File
@@ -0,0 +1,207 @@
name: Publish draft release
on:
workflow_dispatch:
inputs:
ref1:
description: The 'from' tag to use for the diff
default: statemine-v5.0.0
required: true
ref2:
description: The 'to' tag to use for the diff
default: HEAD
required: true
pre_release:
description: For pre-releases
default: "true"
required: true
jobs:
get-rust-versions:
runs-on: ubuntu-latest
container:
image: paritytech/ci-linux:production
outputs:
rustc-stable: ${{ steps.get-rust-versions.outputs.stable }}
rustc-nightly: ${{ steps.get-rust-versions.outputs.nightly }}
steps:
- id: get-rust-versions
run: |
echo "::set-output name=stable::$(rustc +stable --version)"
echo "::set-output name=nightly::$(rustc +nightly --version)"
build-runtimes:
runs-on: ubuntu-latest
strategy:
matrix:
runtime: ["shell", "statemine", "statemint", "westmint", "rococo"]
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Cache target dir
uses: actions/cache@v2
with:
path: "${{ github.workspace }}/runtime/${{ matrix.runtime }}/target"
key: srtool-target-${{ matrix.runtime }}-${{ github.sha }}
restore-keys: |
srtool-target-${{ matrix.runtime }}-
srtool-target-
- name: Build ${{ matrix.runtime }} runtime
id: srtool_build
uses: chevdor/srtool-actions@v0.3.0
with:
image: paritytech/srtool
chain: ${{ matrix.runtime }}
runtime_dir: polkadot-parachains/${{ matrix.runtime }}
- name: Store srtool digest to disk
run: |
echo '${{ steps.srtool_build.outputs.json }}' | \
jq > ${{ matrix.runtime }}_srtool_output.json
- name: Upload ${{ matrix.runtime }} srtool json
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.runtime }}-srtool-json
path: ${{ matrix.runtime }}_srtool_output.json
- name: Upload ${{ matrix.runtime }} runtime
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.runtime }}-runtime
path: |
${{ steps.srtool_build.outputs.wasm_compressed }}
publish-draft-release:
runs-on: ubuntu-latest
needs: ["get-rust-versions", "build-runtimes"]
outputs:
release_url: ${{ steps.create-release.outputs.html_url }}
asset_upload_url: ${{ steps.create-release.outputs.upload_url }}
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
fetch-depth: 0
path: cumulus
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0.0
- name: Download srtool json output
uses: actions/download-artifact@v2
- name: Prepare tooling
run: |
cd cumulus/scripts/changelog
gem install bundler changelogerator
bundle install
changelogerator --help
URL=https://github.com/chevdor/tera-cli/releases/download/v0.2.1/tera-cli_linux_amd64.deb
wget $URL -O tera.deb
sudo dpkg -i tera.deb
tera --version
- name: Generate release notes
env:
RUSTC_STABLE: ${{ needs.get-rust-versions.outputs.rustc-stable }}
RUSTC_NIGHTLY: ${{ needs.get-rust-versions.outputs.rustc-nightly }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NO_CACHE: 1
DEBUG: 1
SHELL_DIGEST: ${{ github.workspace}}/shell-srtool-json/shell_srtool_output.json
WESTMINT_DIGEST: ${{ github.workspace}}/westmint-srtool-json/westmint_srtool_output.json
STATEMINE_DIGEST: ${{ github.workspace}}/statemine-srtool-json/statemine_srtool_output.json
STATEMINT_DIGEST: ${{ github.workspace}}/statemint-srtool-json/statemint_srtool_output.json
ROCOCO_DIGEST: ${{ github.workspace}}/rococo-srtool-json/rococo_srtool_output.json
REF1: ${{ github.event.inputs.ref1 }}
REF2: ${{ github.event.inputs.ref2 }}
PRE_RELEASE: ${{ github.event.inputs.pre_release }}
HIDE_SRTOOL_ROCOCO: false
HIDE_SRTOOL_SHELL: false
run: |
find ${{env.GITHUB_WORKSPACE}} -type f -name "*_srtool_output.json"
ls -al $SHELL_DIGEST
ls -al $WESTMINT_DIGEST
ls -al $STATEMINE_DIGEST
ls -al $STATEMINT_DIGEST
ls -al $ROCOCO_DIGEST
echo "The diff will be computed from $REF1 to $REF2"
cd cumulus/scripts/changelog
./bin/changelog $REF1 $REF2 release-notes.md
ls -al release-notes.md
- name: Create draft release
id: create-release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: parachains-${{ github.ref }}
release_name: Parachains ${{ github.ref }}
body_path: ./cumulus/scripts/changelog/release-notes.md
draft: true
publish-runtimes:
runs-on: ubuntu-latest
needs: ["publish-draft-release"]
env:
RUNTIME_DIR: polkadot-parachains
strategy:
matrix:
runtime: ["shell", "statemine", "statemint", "westmint", "rococo"]
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Download artifacts
uses: actions/download-artifact@v2
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0.0
- name: Get runtime version for ${{ matrix.runtime }}
id: get-runtime-ver
run: |
echo "require './scripts/github/runtime-version.rb'" > script.rb
echo "puts get_runtime(runtime: \"${{ matrix.runtime }}\", runtime_dir: \"$RUNTIME_DIR\")" >> script.rb
echo "Current folder: $PWD"
ls "$RUNTIME_DIR/${{ matrix.runtime }}"
runtime_ver=$(ruby script.rb)
echo "Found version: >$runtime_ver<"
echo "::set-output name=runtime_ver::$runtime_ver"
- name: Upload compressed ${{ matrix.runtime }} wasm
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.publish-draft-release.outputs.asset_upload_url }}
asset_path: "${{ matrix.runtime }}-runtime/${{ matrix.runtime }}_runtime.compact.compressed.wasm"
asset_name: ${{ matrix.runtime }}_runtime-v${{ steps.get-runtime-ver.outputs.runtime_ver }}.compact.compressed.wasm
asset_content_type: application/wasm
post_to_matrix:
runs-on: ubuntu-latest
needs: publish-draft-release
steps:
- name: Internal polkadot channel
uses: s3krit/matrix-message-action@v0.0.3
with:
room_id: ${{ secrets.INTERNAL_POLKADOT_MATRIX_ROOM_ID }}
access_token: ${{ secrets.MATRIX_ACCESS_TOKEN }}
message: |
**New draft for ${{ github.repository }}**: ${{ github.ref }}<br/>
Draft release created: [draft](${{ needs.publish-draft-release.outputs.release_url }})
NOTE: The link above will no longer be valid if the draft is edited. You can then use the following link:
[${{ github.server_url }}/${{ github.repository }}/releases](${{ github.server_url }}/${{ github.repository }}/releases)
server: "matrix.parity.io"
+3
View File
@@ -1 +1,4 @@
changelog.md
*.json
release*.md
.env
+21
View File
@@ -0,0 +1,21 @@
# frozen_string_literal: true
source 'https://rubygems.org'
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
gem 'octokit', '~> 4'
gem 'git_diff_parser', '~> 3'
gem 'toml', '~> 0.3.0'
gem 'rake', group: :dev
gem 'optparse', '~> 0.1.1'
gem 'logger', '~> 1.4'
gem 'test-unit', group: :dev
gem 'rubocop', group: :dev, require: false
+79
View File
@@ -0,0 +1,79 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
ast (2.4.2)
faraday (1.8.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
git_diff_parser (3.2.0)
logger (1.4.4)
multipart-post (2.1.1)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
optparse (0.1.1)
parallel (1.21.0)
parser (3.0.2.0)
ast (~> 2.4.1)
parslet (2.0.0)
power_assert (2.0.1)
public_suffix (4.0.6)
rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
rexml (3.2.5)
rubocop (1.23.0)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.12.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.13.0)
parser (>= 3.0.1.1)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
test-unit (3.5.1)
power_assert
toml (0.3.0)
parslet (>= 1.8.0, < 3.0.0)
unicode-display_width (2.1.0)
PLATFORMS
x86_64-darwin-20
DEPENDENCIES
git_diff_parser (~> 3)
logger (~> 1.4)
octokit (~> 4)
optparse (~> 0.1.1)
rake
rubocop
test-unit
toml (~> 0.3.0)
BUNDLED WITH
2.2.22
+62 -4
View File
@@ -1,13 +1,71 @@
# Changelog
Currently, the changelog is built locally.
Run:
Currently, the changelog is built locally. It will be moved to CI once labels stabilize.
For now, a bit of preparation is required before you can run the script:
- fetch the srtool digests
- store them under the `digests` folder as `<chain>-srtool-digest.json`
- ensure the `.env` file is up to date with correct information
The content of the release notes is generated from the template files under the `scripts/changelog/templates` folder. For readability and maintenance, the template is split into several small snippets.
Run:
```
./changelog.sh <ref_since>
./bin/changelog <ref_since> [<ref_until>=HEAD]
```
For instance:
```
./changelog.sh statemine_v4
./bin/changelog statemine-v5.0.0
```
A file called `release-notes.md` will be generated and can be used for the release.
## ENV
You may use the following ENV for testing:
```
RUSTC_STABLE="rustc 1.56.1 (59eed8a2a 2021-11-01)"
RUSTC_NIGHTLY="rustc 1.57.0-nightly (51e514c0f 2021-09-12)"
PRE_RELEASE=true
HIDE_SRTOOL_ROCOCO=true
HIDE_SRTOOL_SHELL=true
REF1=statemine-v5.0.0
REF2=HEAD
DEBUG=1
NO_CACHE=1
```
## Considered labels
The following list will likely evolve over time and it will be hard to keep it in sync.
In any case, if you want to find all the labels that are used, search for `meta` in the templates.
Currently, the considered labels are:
- Priority: C<N> labels
- Audit: D<N> labels
- E4 => new host function
- B0 => silent, not showing up
- B1-releasenotes (misc unless other labels)
- B5-client (client changes)
- B7-runtimenoteworthy (runtime changes)
- T6-XCM
Note that labels with the same letter are mutually exclusive.
A PR should not have both `B0` and `B5`, or both `C1` and `C9`. In case of conflicts, the template will
decide which label will be considered.
## Dev and debuggin
### Hot Reload
The following command allows **Hot Reload**:
```
fswatch templates -e ".*\.md$" | xargs -n1 -I{} ./bin/changelog statemine-v5.0.0
```
### Caching
By default, if the changelog data from Github is already present, the calls to the Github API will be skipped
and the local version of the data will be used. This is much faster.
If you know that some labels have changed in Github, you probably want to refresh the data.
You can then either delete manually the `cumulus.json` file or `export NO_CACHE=1` to force refreshing the data.
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
# call for instance as:
# ./bin/changelog statemine-v5.0.0
#
# You may set the ENV NO_CACHE to force fetching from Github
# You should also ensure you set the ENV: GITHUB_TOKEN
require_relative '../lib/changelog'
require 'logger'
logger = Logger.new($stdout)
logger.level = Logger::DEBUG
logger.debug('Starting')
owner = 'paritytech'
repo = 'cumulus'
ref1 = ARGV[0]
ref2 = ARGV[1] || 'HEAD'
output = ARGV[2] || 'release-notes.md'
ENV['REF1'] = ref1
ENV['REF2'] = ref2
gh_cumulus = SubRef.new(format('%<owner>s/%<repo>s', { owner: owner, repo: repo }))
polkadot_ref1 = gh_cumulus.get_dependency_reference(ref1, 'polkadot-client')
polkadot_ref2 = gh_cumulus.get_dependency_reference(ref2, 'polkadot-client')
substrate_ref1 = gh_cumulus.get_dependency_reference(ref1, 'sp-io')
substrate_ref2 = gh_cumulus.get_dependency_reference(ref2, 'sp-io')
logger.debug("Polkadot from: #{polkadot_ref1}")
logger.debug("Polkadot to: #{polkadot_ref2}")
logger.debug("Substrate from: #{substrate_ref1}")
logger.debug("Substrate to: #{substrate_ref2}")
cumulus_data = 'cumulus.json'
substrate_data = 'substrate.json'
polkadot_data = 'polkadot.json'
logger.debug("Using CUMULUS: #{cumulus_data}")
logger.debug("Using SUBSTRATE: #{substrate_data}")
logger.debug("Using POLKADOT: #{polkadot_data}")
logger.warn('NO_CACHE set') if ENV['NO_CACHE']
# This is acting as cache so we don't spend time querying while testing
if ENV['NO_CACHE'] || !File.file?(cumulus_data)
logger.debug(format('Fetching data for Cumulus into %s', cumulus_data))
cmd = format('changelogerator %<owner>s/%<repo>s -f %<from>s -t %<to>s > %<output>s',
{ owner: owner, repo: repo, from: ref1, to: ref2, output: cumulus_data })
system(cmd)
else
logger.debug("Re-using:#{cumulus_data}")
end
if ENV['NO_CACHE'] || !File.file?(polkadot_data)
logger.debug(format('Fetching data for Polkadot into %s', polkadot_data))
cmd = format('changelogerator %<owner>s/%<repo>s -f %<from>s -t %<to>s > %<output>s',
{ owner: owner, repo: 'polkadot', from: polkadot_ref1, to: polkadot_ref2, output: polkadot_data })
system(cmd)
else
logger.debug("Re-using:#{polkadot_data}")
end
if ENV['NO_CACHE'] || !File.file?(substrate_data)
logger.debug(format('Fetching data for Substrate into %s', substrate_data))
cmd = format('changelogerator %<owner>s/%<repo>s -f %<from>s -t %<to>s > %<output>s',
{ owner: owner, repo: 'substrate', from: substrate_ref1, to: substrate_ref2, output: substrate_data })
system(cmd)
else
logger.debug("Re-using:#{substrate_data}")
end
SHELL_DIGEST = ENV['SHELL_DIGEST'] || 'digests/shell-srtool-digest.json'
WESTMINT_DIGEST = ENV['WESTMINT_DIGEST'] || 'digests/westmint-srtool-digest.json'
STATEMINE_DIGEST = ENV['STATEMINE_DIGEST'] || 'digests/statemine-srtool-digest.json'
STATEMINT_DIGEST = ENV['STATEMINT_DIGEST'] || 'digests/rococo-srtool-digest.json'
ROCOCO_DIGEST = ENV['ROCOCO_DIGEST'] || 'digests/rococo-srtool-digest.json'
# Here we compose all the pieces together into one
# single big json file.
cmd = format('jq \
--slurpfile cumulus %s \
--slurpfile substrate %s \
--slurpfile polkadot %s \
--slurpfile srtool_shell %s \
--slurpfile srtool_westmint %s \
--slurpfile srtool_statemine %s \
--slurpfile srtool_statemint %s \
--slurpfile srtool_rococo %s \
-n \'{
cumulus: $cumulus[0],
substrate: $substrate[0],
polkadot: $polkadot[0],
srtool: [
{ name: "rococo", data: $srtool_rococo[0] },
{ name: "shell", data: $srtool_shell[0] },
{ name: "westmint", data: $srtool_westmint[0] },
{ name: "statemint", data: $srtool_statemint[0] },
{ name: "statemine", data: $srtool_statemine[0] }
] }\' > context.json', cumulus_data, substrate_data, polkadot_data,
SHELL_DIGEST,
WESTMINT_DIGEST,
STATEMINE_DIGEST,
STATEMINT_DIGEST,
ROCOCO_DIGEST)
system(cmd)
cmd = format('tera --env --env-key env --include-path templates \
--template templates/template.md.tera context.json > %s', output)
system(cmd)
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env bash
REF1=$1
JSON=$(git log $REF1..HEAD \
--pretty=format:'{ "commit": "%H", "short_sha": "%h", "author": "%an", "date": "%ad", "message": "%s"},' \
$@ | \
perl -pe 'BEGIN{print "{ \"since\": \"'${REF1}'\", \"commits\": ["}; END{print "]}"}' | \
perl -pe 's/},]/}]/')
echo $JSON | tera --template templates/changelog.md --stdin | tee
@@ -0,0 +1 @@
*.json
@@ -0,0 +1,32 @@
# frozen_string_literal: true
# A Class to find Substrate references
class SubRef
require 'octokit'
require 'toml'
attr_reader :client, :repository
def initialize(github_repo)
@client = Octokit::Client.new(
access_token: ENV['GITHUB_TOKEN']
)
@repository = @client.repository(github_repo)
end
# This function checks the Cargo.lock of a given
# Rust project, for a given package, and fetches
# the dependency git ref.
def get_dependency_reference(ref, package)
cargo = TOML::Parser.new(
Base64.decode64(
@client.contents(
@repository.full_name,
path: 'Cargo.lock',
query: { ref: ref.to_s }
).content
)
).parsed
cargo['package'].find { |p| p['name'] == package }['source'].split('#').last
end
end
@@ -0,0 +1,45 @@
{# This macro shows ONE change #}
{%- macro change(c, cml="[C]", dot="[P]", sub="[S]") -%}
{%- if c.meta.C and c.meta.C.value >= 7 -%}
{%- set prio = " ‼️ HIGH" -%}
{%- elif c.meta.C and c.meta.C.value >= 5 -%}
{%- set prio = " ❗️ Medium" -%}
{%- elif c.meta.C and c.meta.C.value >= 3 -%}
{%- set prio = " Low" -%}
{%- else -%}
{%- set prio = "" -%}
{%- endif -%}
{%- set audit = "" -%}
{#
{%- if c.meta.D and c.meta.D.value == 1 -%}
{%- set audit = "✅ audited " -%}
{%- elif c.meta.D and c.meta.D.value == 2 -%}
{%- set audit = "✅ trivial " -%}
{%- elif c.meta.D and c.meta.D.value == 3 -%}
{%- set audit = "✅ trivial " -%}
{%- elif c.meta.D and c.meta.D.value == 5 -%}
{%- set audit = "⏳ pending non-critical audit " -%}
{%- else -%}
{%- set audit = "" -%}
{%- endif -%}
#}
{%- if c.html_url is containing("polkadot") -%}
{%- set repo = dot -%}
{%- elif c.html_url is containing("cumulus") -%}
{%- set repo = cml -%}
{%- elif c.html_url is containing("substrate") -%}
{%- set repo = sub -%}
{%- else -%}
{%- set repo = " " -%}
{%- endif -%}
{%- if c.meta.T and c.meta.T.value == 6 -%}
{%- set xcm = " [✉️ XCM]" -%}
{%- else -%}
{%- set xcm = "" -%}
{%- endif -%}
{{- repo }} {{ audit }}[`#{{c.number}}`]({{c.html_url}}) {{- prio }} - {{ c.title | capitalize | truncate(length=60, end="…") }}{{xcm }}
{%- endmacro change -%}
@@ -0,0 +1,14 @@
{# This include generates the section showing the changes #}
## Changes
### Legend
- {{ CML }} Cumulus
- {{ DOT }} Polkadot
- {{ SUB }} Substrate
{% include "changes_client.md.tera" %}
{% include "changes_runtime.md.tera" %}
{% include "changes_misc.md.tera" %}
@@ -0,0 +1,17 @@
{% import "change.md.tera" as m_c -%}
### Client
{#- The changes are sorted by merge date #}
{%- for pr in changes | sort(attribute="merged_at") %}
{%- if pr.meta.B %}
{%- if pr.meta.B.value == 0 %}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.B.value == 5 and not pr.title is containing("ompanion") %}
- {{ m_c::change(c=pr) }}
{%- endif -%}
{% endif -%}
{% endif -%}
{% endfor %}
@@ -0,0 +1,39 @@
{%- import "change.md.tera" as m_c -%}
{%- set_global misc_count = 0 -%}
{#- First pass to count #}
{%- for pr in changes -%}
{%- if pr.meta.B %}
{%- if pr.meta.B.value == 0 -%}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.B and pr.meta.B.value != 5 and pr.meta.B.value != 7 or pr.meta.C or not pr.meta.B %}
{%- set_global misc_count = misc_count + 1 -%}
{%- endif -%}
{% endif -%}
{% endif -%}
{% endfor %}
### Misc
{% if misc_count > 10 %}
There are {{ misc_count }} other misc. changes. You can expand the list below to view them all.
<details><summary>{{ misc_count }} misc. changes</summary>
{% endif -%}
{#- The changes are sorted by merge date #}
{%- for pr in changes | sort(attribute="merged_at") %}
{%- if pr.meta.B and not pr.title is containing("ompanion") %}
{%- if pr.meta.B.value == 0 %}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.B and pr.meta.B.value != 5 and pr.meta.B.value != 7 or pr.meta.C or not pr.meta.B %}
- {{ m_c::change(c=pr) }}
{%- endif -%}
{% endif -%}
{% endif -%}
{% endfor %}
{% if misc_count > 10 %}
</details>
{% endif -%}
@@ -0,0 +1,19 @@
{%- import "change.md.tera" as m_c -%}
### Runtime
{#- The changes are sorted by merge date -#}
{% for pr in changes | sort(attribute="merged_at") -%}
{%- if pr.meta.B -%}
{%- if pr.meta.B.value == 0 -%}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.B.value == 7 and not pr.title is containing("ompanion") %}
- {{ m_c::change(c=pr) }}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor %}
@@ -0,0 +1,6 @@
## Rust compiler versions
This release was tested against the following versions of `rustc`. Other versions may work.
- Rust Stable: `{{ env.RUSTC_STABLE }}`
- Rust Nightly: `{{ env.RUSTC_NIGHTLY }}`
@@ -0,0 +1,10 @@
{%- set to_ignore = changes | filter(attribute="meta.B.value", value=0) %}
<!--
## Debug
changes:
- total: {{ changes | length }}
- silent: {{ to_ignore | length }}
- remaining: {{ changes | length - to_ignore | length }}
-->
@@ -0,0 +1,10 @@
<!--
## Docker images
The docker image for this release can be found in [Docker hub](https://hub.docker.com/r/parity/polkadot-collator/tags?page=1&ordering=last_updated).
You may also pull it with:
```
docker pull parity/polkadot-collator:latest
```
-->
@@ -0,0 +1,37 @@
{% import "priority.md.tera" as m_p -%}
## Global Priority
{%- set cumulus_prio = 0 -%}
{%- set polkadot_prio = 0 -%}
{%- set substrate_prio = 0 -%}
{# We fetch the various priorities #}
{%- if cumulus.meta.C -%}
{%- set cumulus_prio = cumulus.meta.C.max -%}
{%- endif -%}
{%- if polkadot.meta.C -%}
{%- set polkadot_prio = polkadot.meta.C.max -%}
{%- endif -%}
{%- if substrate.meta.C -%}
{%- set substrate_prio = substrate.meta.C.max -%}
{%- endif -%}
{# We compute the global priority #}
{%- set global_prio = cumulus_prio -%}
{%- if polkadot_prio > global_prio -%}
{% set global_prio = polkadot_prio -%}
{%- endif -%}
{%- if substrate_prio > global_prio -%}
{%- set global_prio = substrate_prio -%}
{%- endif -%}
{# We show the result #}
{{ m_p::priority(p=global_prio) }}
<!--
- Cumulus: {{ cumulus_prio }}
- Polkadot: {{ polkadot_prio }}
- Substrate: {{ substrate_prio }}
-->
{# todo: show high prio list here #}
@@ -0,0 +1,30 @@
{%- import "change.md.tera" as m_c -%}
{%- set_global host_fn_count = 0 -%}
## Host functions
{% for pr in changes | sort(attribute="merged_at") -%}
{%- if pr.meta.B and pr.meta.B.value == 0 -%}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.E and pr.meta.E.value == 4 -%}
{%- set_global host_fn_count = host_fn_count + 1 -%}
- {{ m_c::change(c=pr) }}
{% endif -%}
{% endif -%}
{%- endfor -%}
<!-- {{ host_fn_count }} host functions were detected -->
{% if host_fn_count == 0 -%}
️ This release does not contain any new host functions.
{% elif host_fn_count == 1 -%}
⚠️ The runtimes in this release contain one new **host function**.
⚠️ It is critical that you update your client before the chain switches to the new runtimes.
{%- else -%}
⚠️ The runtimes in this release contain {{ host_fn_count }} new **host function{{ host_fn_count | pluralize }}**.
⚠️ It is critical that you update your client before the chain switches to the new runtimes.
{%- endif %}
@@ -0,0 +1,14 @@
{%- import "change.md.tera" as m_c %}
## Migrations
{% for pr in changes | sort(attribute="merged_at") -%}
{%- if pr.meta.B and pr.meta.B.value == 0 %}
{#- We skip silent ones -#}
{%- else -%}
{%- if pr.meta.E and pr.meta.E.value == 1 -%}
- {{ m_c::change(c=pr) }}
{% endif -%}
{% endif -%}
{% endfor -%}
@@ -0,0 +1,9 @@
{%- if env.PRE_RELEASE == "true" -%}
-----
⚠️ Howdy! Beware, this is a **pre-release**
-----
{%- else -%}
<!-- NOT a pre-release-->
{%- endif %}
@@ -0,0 +1,21 @@
{# This macro convert a priority level into readable output #}
{%- macro priority(p) -%}
{%- if p >= 7 -%}
{%- set prio = "‼️ HIGH" -%}
{%- set text = "This is a **high priority** release and you must upgrade as as soon as possible" -%}
{%- elif p >= 5 -%}
{%- set prio = "❗️ Medium" -%}
{%- set text = "This is a medium priority release and you should upgrade in a timely manner" -%}
{%- elif p >= 3 -%}
{%- set prio = "Low" -%}
{%- set text = "This is a low priority release and you may upgrade at your convenience" -%}
{%- endif %}
{%- if prio %}
{{prio}}: {{text}}
{%- else -%}
<!-- No relevant Priority label as been detected -->
{% endif %}
{%- endmacro priority -%}
@@ -0,0 +1,27 @@
{# This macro shows one runtime #}
{%- macro runtime(runtime) -%}
### {{ runtime.name | capitalize }}
{%- if runtime.data.runtimes.compressed.subwasm.compression.compressed %}
{%- set compressed = "Yes" %}
{%- else %}
{%- set compressed = "No" %}
{%- endif %}
{%- set comp_ratio = 100 - (runtime.data.runtimes.compressed.subwasm.compression.size_compressed / runtime.data.runtimes.compressed.subwasm.compression.size_decompressed *100) %}
<!-- commit : {{ runtime.data.commit }} -->
<!-- tag : {{ runtime.data.tag }} -->
<!-- branch : {{ runtime.data.branch }} -->
<!-- pkg : {{ runtime.data.pkg }} -->
```
🏋️ Runtime Size: {{ runtime.data.runtimes.compressed.subwasm.size | filesizeformat }} ({{ runtime.data.runtimes.compressed.subwasm.size }} bytes)
🔥 Core Version: {{ runtime.data.runtimes.compressed.subwasm.core_version }}
🗜 Compressed: {{ compressed }}: {{ comp_ratio | round(method="ceil", precision=2) }}%
🎁 Metadata version: {{ runtime.data.runtimes.compressed.subwasm.metadata_version }}
🗳️ system.setCode hash: {{ runtime.data.runtimes.compressed.subwasm.proposal_hash }}
🗳️ authorizeUpgrade hash: {{ runtime.data.runtimes.compressed.subwasm.parachain_authorize_upgrade_hash }}
#️⃣ Blake2-256 hash: {{ runtime.data.runtimes.compressed.subwasm.blake2_256 }}
📦 IPFS: {{ runtime.data.runtimes.compressed.subwasm.ipfs_hash }}
```
{%- endmacro runtime %}
@@ -0,0 +1,17 @@
{# This include shows the list and details of the runtimes #}
{%- import "runtime.md.tera" as m_r -%}
## Runtimes
{% set rtm = srtool[0] -%}
The information about the runtimes included in this release can be found below.
The runtimes have been built using [{{ rtm.data.gen }}](https://github.com/paritytech/srtool) and `{{ rtm.data.rustc }}`.
{%- for runtime in srtool | sort(attribute="name") %}
{%- set HIDE_VAR = "HIDE_SRTOOL_" ~ runtime.name | upper %}
{%- if not env is containing(HIDE_VAR) %}
{{ m_r::runtime(runtime=runtime) }}
{%- endif %}
{%- endfor %}
@@ -0,0 +1,28 @@
{# This is the entry point of the template -#}
<!-- repository: {{ cumulus.repository.name }} -->
This release contains the changes from `{{ env.REF1 }}` to `{{ env.REF2 }}`.
{%- set changes = cumulus.changes | concat(with=substrate.changes) -%}
{%- set changes = changes | concat(with=polkadot.changes) -%}
{%- include "debug.md.tera" -%}
{%- set CML = "[C]" -%}
{%- set DOT = "[P]" -%}
{%- set SUB = "[S]" -%}
{# header warning and important notices -#}
{% include "pre_release.md.tera" -%}
{% include "global_priority.md.tera" -%}
{% include "host_functions.md.tera" -%}
{% include "compiler.md.tera" -%}
{% include "migrations.md.tera" -%}
{% include "runtimes.md.tera" -%}
{% include "changes.md.tera" -%}
{% include "docker_image.md.tera" -%}
+23
View File
@@ -0,0 +1,23 @@
# frozen_string_literal: true
require_relative '../lib/changelog'
require 'test/unit'
class TestChangelog < Test::Unit::TestCase
def test_get_dep_ref_polkadot
c = SubRef.new('paritytech/polkadot')
ref = '13c2695'
package = 'sc-cli'
result = c.get_dependency_reference(ref, package)
assert_equal('7db0768a85dc36a3f2a44d042b32f3715c00a90d', result)
end
def test_get_dep_ref_invalid_ref
c = SubRef.new('paritytech/polkadot')
ref = '9999999'
package = 'sc-cli'
assert_raise do
c.get_dependency_reference(ref, package)
end
end
end
+10
View File
@@ -0,0 +1,10 @@
# frozen_string_literal: true
# Gets the runtime version for a given runtime from the filesystem.
# Optionally accepts a path that is the root of the project which defaults to
# the current working directory
def get_runtime(runtime: nil, path: '.', runtime_dir: 'runtime')
File.open(path + "/#{runtime_dir}/#{runtime}/src/lib.rs") do |f|
f.find { |l| l =~ /spec_version/ }.match(/[0-9]+/)[0]
end
end