diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 984556a03..749ea7fa1 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,8 +1,8 @@
## Pull Request Checklist
- [ ] The Certbot team has recently expressed interest in reviewing a PR for this. If not, this PR may be closed due our limited resources and need to prioritize how we spend them.
-- [ ] If you used AI to create this PR, you have done a self-review of all AI-generated code and disclosed that your contribution was AI-generated per [EFF's AI-generated contribution policy](https://www.eff.org/about/opportunities/volunteer/coding-with-eff). You assert you have thoroughly understood, reviewed, and tested your entire submission.
+- [ ] If you used AI to create this PR, you have done a self-review of all AI-generated code and disclosed that your contribution was AI-generated per [EFF's AI-generated contribution policy](https://www.eff.org/about/opportunities/volunteer/coding-with-eff#ai-policy). You assert you have thoroughly understood, reviewed, and tested your entire submission.
- [ ] If the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), add a description of your change to the `newsfragments` directory. This should be a file called `
.`, where `` is either a GitHub issue number or some other unique name starting with `+`, and `` is either `changed`, `fixed`, or `added`.
* For example, if you fixed a bug for issue number 42, create a file called `42.fixed` and put a description of your change in that file.
- [ ] Add or update any documentation as needed to support the changes in this PR.
-- [ ] Include your name in `AUTHORS.md` if you like.
\ No newline at end of file
+- [ ] Include your name in `AUTHORS.md` if you like.
diff --git a/.github/workflows/notify_weekly.yaml b/.github/workflows/notify_weekly.yaml
deleted file mode 100644
index 6d55a43d0..000000000
--- a/.github/workflows/notify_weekly.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-name: Weekly Github Update
-
-on:
- schedule:
- # Every week on Thursday @ 10:00
- - cron: "0 10 * * 4"
- workflow_dispatch:
-permissions: {} # let's not use any permissions we don't need here
-jobs:
- send-mattermost-message:
- runs-on: ubuntu-latest
-
- steps:
- - name: Create Mattermost Message
- run: |
- DATE=$(date --date="7 days ago" +"%Y-%m-%d")
- echo "ASSIGNED_PRS=https://github.com/pulls?q=is%3Apr+is%3Aopen+updated%3A%3E%3D${DATE}+assignee%3A*+user%3Acertbot" >> $GITHUB_ENV
- echo "UPDATED_URL=https://github.com/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc+updated%3A%3E%3D${DATE}+user%3Acertbot" >> $GITHUB_ENV
- # we pin this action to a version tested and audited by certbot's
- # maintainers for extra security. the full hash is used as doing so is
- # recommended by zizmor
- - uses: mattermost/action-mattermost-notify@ae31bb6f9e26a54336e79696f108a2c91cf55b4e
- with:
- MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
- MATTERMOST_CHANNEL: private-certbot
- TEXT: |
- ## Updates In the Past Week
- - Most commented in the last week: [link](${{ env.UPDATED_URL }})
- - Updated (assigned) PRs in the last week: [link](${{ env.ASSIGNED_PRS }})
diff --git a/.github/workflows/snap_packaging_jobs.yml b/.github/workflows/snap_packaging_jobs.yml
index 58d2bb75f..5cebb9f9d 100644
--- a/.github/workflows/snap_packaging_jobs.yml
+++ b/.github/workflows/snap_packaging_jobs.yml
@@ -46,7 +46,7 @@ jobs:
persist-credentials: false
- id: set-dns-dirs
run: |
- DNS_NAMES="$(echo certbot-dns-* | jq -R -s -c 'split(" ")[:-1]')"
+ DNS_NAMES="$(echo certbot-dns-* | jq -R -s -c 'gsub("\n"; "") | split(" ")')"
echo "dns-dirs=$DNS_NAMES" >> "$GITHUB_OUTPUT"
gha_build_dns_snaps:
name: Build ${{ matrix.dns-dir }} ${{ matrix.build-for }}
diff --git a/acme/setup.py b/acme/setup.py
index c36a455ac..11fc858b9 100644
--- a/acme/setup.py
+++ b/acme/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
setup(
version=version,
diff --git a/certbot-apache/setup.py b/certbot-apache/setup.py
index dc99a4b1c..ce89349b7 100644
--- a/certbot-apache/setup.py
+++ b/certbot-apache/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
# We specify the minimum certbot version as the current plugin
diff --git a/certbot-ci/setup.py b/certbot-ci/setup.py
index c36a455ac..11fc858b9 100644
--- a/certbot-ci/setup.py
+++ b/certbot-ci/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
setup(
version=version,
diff --git a/certbot-compatibility-test/setup.py b/certbot-compatibility-test/setup.py
index c36a455ac..11fc858b9 100644
--- a/certbot-compatibility-test/setup.py
+++ b/certbot-compatibility-test/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
setup(
version=version,
diff --git a/certbot-dns-cloudflare/setup.py b/certbot-dns-cloudflare/setup.py
index f6055686f..6d8ec386d 100644
--- a/certbot-dns-cloudflare/setup.py
+++ b/certbot-dns-cloudflare/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'cloudflare>=4.0',
diff --git a/certbot-dns-digitalocean/setup.py b/certbot-dns-digitalocean/setup.py
index 70ac37eeb..0925986d4 100644
--- a/certbot-dns-digitalocean/setup.py
+++ b/certbot-dns-digitalocean/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'python-digitalocean>=1.15.0', # 1.15.0 or newer is recommended for TTL support
diff --git a/certbot-dns-dnsimple/setup.py b/certbot-dns-dnsimple/setup.py
index 475972dfc..8e16f34db 100644
--- a/certbot-dns-dnsimple/setup.py
+++ b/certbot-dns-dnsimple/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
# This version of lexicon is required to address the problem described in
diff --git a/certbot-dns-dnsmadeeasy/setup.py b/certbot-dns-dnsmadeeasy/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-dnsmadeeasy/setup.py
+++ b/certbot-dns-dnsmadeeasy/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-dns-gehirn/setup.py b/certbot-dns-gehirn/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-gehirn/setup.py
+++ b/certbot-dns-gehirn/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-dns-google/setup.py b/certbot-dns-google/setup.py
index 0fa111ae8..c20f69072 100644
--- a/certbot-dns-google/setup.py
+++ b/certbot-dns-google/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'google-api-python-client>=1.6.5',
diff --git a/certbot-dns-linode/setup.py b/certbot-dns-linode/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-linode/setup.py
+++ b/certbot-dns-linode/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-dns-luadns/setup.py b/certbot-dns-luadns/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-luadns/setup.py
+++ b/certbot-dns-luadns/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-dns-nsone/setup.py b/certbot-dns-nsone/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-nsone/setup.py
+++ b/certbot-dns-nsone/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-dns-ovh/setup.py b/certbot-dns-ovh/setup.py
index 0673d5bcc..0f91af742 100644
--- a/certbot-dns-ovh/setup.py
+++ b/certbot-dns-ovh/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.15.1',
diff --git a/certbot-dns-rfc2136/setup.py b/certbot-dns-rfc2136/setup.py
index 5dece69aa..271c75fcc 100644
--- a/certbot-dns-rfc2136/setup.py
+++ b/certbot-dns-rfc2136/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
# This version was chosen because it is the version packaged in RHEL 9 and Debian unstable. It
diff --git a/certbot-dns-route53/setup.py b/certbot-dns-route53/setup.py
index ac93625ab..1893beacc 100644
--- a/certbot-dns-route53/setup.py
+++ b/certbot-dns-route53/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'boto3>=1.20.34',
diff --git a/certbot-dns-sakuracloud/setup.py b/certbot-dns-sakuracloud/setup.py
index 2d32dacbd..e17fd5066 100644
--- a/certbot-dns-sakuracloud/setup.py
+++ b/certbot-dns-sakuracloud/setup.py
@@ -2,7 +2,7 @@ import os
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
'dns-lexicon>=3.14.1',
diff --git a/certbot-nginx/setup.py b/certbot-nginx/setup.py
index 8ae070825..876a39197 100644
--- a/certbot-nginx/setup.py
+++ b/certbot-nginx/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
install_requires = [
# We specify the minimum certbot version as the current plugin
diff --git a/certbot/CHANGELOG.md b/certbot/CHANGELOG.md
index eb8a2bc42..f020c279d 100644
--- a/certbot/CHANGELOG.md
+++ b/certbot/CHANGELOG.md
@@ -4,6 +4,13 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
+## 5.7.0 - 2026-07-15
+
+### Fixed
+
+- Fixed nginx configuration parsing when comments appear between tokens of a multi-line directive. ([#10598](https://github.com/certbot/certbot/issues/10598))
+
+
## 5.6.0 - 2026-05-11
### Changed
diff --git a/certbot/docs/cli-help.txt b/certbot/docs/cli-help.txt
index 053716b4b..bc55950d8 100644
--- a/certbot/docs/cli-help.txt
+++ b/certbot/docs/cli-help.txt
@@ -147,7 +147,7 @@ options:
case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to
- "". (default: CertbotACMEClient/5.6.0 (certbot;
+ "". (default: CertbotACMEClient/5.7.0 (certbot;
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
The flags encoded in the user agent are: --duplicate,
diff --git a/certbot/docs/using.rst b/certbot/docs/using.rst
index e64fcf9cb..9350b0f04 100644
--- a/certbot/docs/using.rst
+++ b/certbot/docs/using.rst
@@ -336,6 +336,7 @@ pkcs12_ N Y Install certificates as PKCS#12 archives
dns-hetzner-cloud_ Y N DNS Authentication for Hetzner Cloud DNS
dns-czechia_ Y N DNS Authentication for czechia.com
dns-eurodns_ Y N DNS Authentication for EuroDNS
+dns-dnscale_ Y N DNS Authenticator for DNScale
======================= ==== ==== =================================================================
.. _haproxy: https://github.com/greenhost/certbot-haproxy
@@ -373,6 +374,7 @@ dns-eurodns_ Y N DNS Authentication for EuroDNS
.. _dns-hetzner-cloud: https://github.com/rolschewsky/certbot-dns-hetzner-cloud
.. _dns-czechia: https://github.com/CZECHIA-COM/certbot-dns-czechia
.. _dns-eurodns: https://pypi.org/project/certbot-dns-eurodns/
+.. _dns-dnscale: https://github.com/dnscaleou/certbot-dns-dnscale
If you're interested, you can also :ref:`write your own plugin `.
diff --git a/certbot/src/certbot/__init__.py b/certbot/src/certbot/__init__.py
index b467db186..8da3222d9 100644
--- a/certbot/src/certbot/__init__.py
+++ b/certbot/src/certbot/__init__.py
@@ -1,4 +1,4 @@
"""Certbot client."""
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
-__version__ = '5.7.0.dev0'
+__version__ = '5.8.0.dev0'
diff --git a/letstest/setup.py b/letstest/setup.py
index c36a455ac..11fc858b9 100644
--- a/letstest/setup.py
+++ b/letstest/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup
-version = '5.7.0.dev0'
+version = '5.8.0.dev0'
setup(
version=version,
diff --git a/newsfragments/10598.fixed b/newsfragments/10598.fixed
deleted file mode 100644
index f0a68b533..000000000
--- a/newsfragments/10598.fixed
+++ /dev/null
@@ -1 +0,0 @@
-Fixed nginx configuration parsing when comments appear between tokens of a multi-line directive.
diff --git a/tools/_release.sh b/tools/_release.sh
index 95f722f00..82e15924e 100755
--- a/tools/_release.sh
+++ b/tools/_release.sh
@@ -103,6 +103,7 @@ tools/pip_install.py build towncrier uv virtualenv
root_without_le="$version.$$"
root="$RELEASE_DIR/le.$root_without_le"
+REPO_ROOT="$(pwd)"
echo "Cloning into fresh copy at $root" # clean repo = no artifacts
git clone . $root
@@ -215,5 +216,10 @@ git commit -m "Remove built packages from git"
if [ "$RELEASE_BRANCH" = candidate-"$version" ] ; then
SetVersion "$nextversion".dev0
+ # If this message changes, it should also be changed in tools/finish_release.py
git commit -m "Bump version to $nextversion"
fi
+
+cd $REPO_ROOT
+git remote rm temp || :
+git remote add temp $root && git fetch temp
diff --git a/tools/finish_release.py b/tools/finish_release.py
index 4b2e3e32c..23858e412 100755
--- a/tools/finish_release.py
+++ b/tools/finish_release.py
@@ -1,24 +1,38 @@
#!/usr/bin/env python
"""
-Post-release script to publish artifacts created from GitHub Actions.
+Post-release script to publish artifacts created from GitHub Actions, synchronize the repo
+ on Github, and print a formatted changelog for the latest release.
This currently includes:
* Moving snaps from the beta channel to the stable channel
+* Pushing the candidate branch to GitHub
+* Creating a minor release branch if it's not a point release
+* Opening PR(s) to merge the release changes back into `main` and/or the minor release branch
+* Printing a formmated changelog for the latest release for distribution
Setup:
- - Install the snapcraft command line tool and log in to a privileged account.
+ - Install the `snapcraft` command line tool and log in to a privileged account.
- https://snapcraft.io/docs/installing-snapcraft
- Use the command `snapcraft login` to log in.
+ - Install the `gh` command line tool and log in to a privileged account.
+ - https://github.com/cli/cli#installation
+ - Use the command `gh auth login` to log in.
Run:
-python tools/finish_release.py
+python tools/finish_release.py [--skip-snaps] [--skip-github-sync] [--test version ]
Testing:
This script can be safely run between releases. When this is done, the script
-should execute successfully.
+should execute successfully, if it has not run before. Promoting snaps from beta
+and printing the changelog are idempotent, but synchronizing the github repo is not.
+
+To skip syncing with github, use the `--skip-github-sync` flag.
+To skip promoting snaps, use the `--skip-snaps` flag.
+To test with a version other than the latest release, use the `--test-version ` flag
+ with a version number formatted as .
"""
@@ -45,6 +59,8 @@ ALL_SNAPS = ['certbot'] + PLUGIN_SNAPS
# This is the count of the architectures currently supported by our snaps used
# for sanity checking.
SNAP_ARCH_COUNT = 3
+SKIP_SYNC_MESSAGE = ('To skip pushing updated branches to GitHub and creating PRs, '
+ 'run this script with the `--skip-github-sync` flag.')
def parse_args(args):
@@ -61,6 +77,12 @@ def parse_args(args):
# Use the file's docstring for the help text and don't let argparse reformat it.
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.add_argument('--test-version', type=str, default=None,
+ help='version in the form of 1.2.3, mainly for testing')
+ parser.add_argument('--skip-snaps', action='store_true',
+ help='don\'t promote snaps; used for testing')
+ parser.add_argument('--skip-github-sync', action='store_true',
+ help='don\'t synchronize branches to GitHub or create PRs')
return parser.parse_args(args)
@@ -171,6 +193,145 @@ def fetch_version_number():
assert len(version.split('.')) == 3
return version
+
+def _run_silent_except_error(cmd: list[str], message: str = None) -> subprocess.CompletedProcess:
+ # For some reason, git prints a bunch of non-error output to stderr. Let's keep this script
+ # quiet by capturing it and only printing it if we hit an error.
+ try:
+ process = subprocess.run(cmd, check=True, universal_newlines=True, capture_output=True)
+ except subprocess.CalledProcessError as e:
+ print(f'Error running `{" ".join(cmd)}`')
+ if message is not None:
+ print(message)
+ print(e.output)
+ print(e.stderr)
+ print(SKIP_SYNC_MESSAGE)
+ raise e
+ else:
+ return process
+
+
+def _create_pr(title: str, body: str, description: str, other_opts: list[str] | None = None) -> str:
+ cmd = ['gh', 'pr', 'create', '--title', title, '--body', body]
+ if other_opts is not None:
+ cmd = cmd + other_opts
+ try:
+ proc = subprocess.run(cmd, check=True, universal_newlines=True, capture_output=True)
+ except subprocess.CalledProcessError as e:
+ if 'already exists' in e.stderr:
+ print(f'{description} already exists...skipping creation. '
+ 'To create a new PR, delete the old one on GitHub.')
+ # The error message looks like:
+ # a pull request for branch "candidate-4.24.0" into branch "main" already exists:
+ # https://github.com/certbot/certbot/pull/10698
+ last_e_word = e.stderr.split()[-1]
+ if 'https' in last_e_word:
+ output = last_e_word
+ else:
+ print(e.stderr)
+ print(SKIP_SYNC_MESSAGE)
+ raise e
+ else:
+ output = proc.stdout.rstrip()
+ return output
+
+
+def _sync_candidate_from_temp_to_origin(version: str) -> None:
+ command_str = f'git pull temp candidate-{version}'
+ message = ('To run successfully, stash any changes you\'ve made to this branch. '
+ 'Do not attempt to merge and continue, as that will fail.')
+ _run_silent_except_error(command_str.split(), message)
+ command_str = f'git push origin candidate-{version}'
+ message = ('To delete the branch on GitHub, run '
+ f'`git push origin --delete candidate-{version}`.')
+ _run_silent_except_error(command_str.split(), message)
+
+
+def _create_release_pr_to_main(version: str) -> None:
+ print(f'Creating PR to merge candidate-{version} into main...')
+ title = f'update files from {version} release'
+ body = 'this PR only needs 1 review and should be merged, not squashed'
+ result = _create_pr(title, body, 'PR to merge release changes into main')
+ print(f'PR location: {result}')
+
+
+def _create_release_pr_to_minor_branch(
+ version: str,
+ branch_name:str,
+ point_x_branch_name: str) -> None:
+ print(f'Creating PR to merge {branch_name} into {point_x_branch_name}...')
+ title = f'update files from {version} release'
+ body = 'this PR only needs 1 review and should be merged, not squashed'
+ pr_opts = [ '--head', branch_name,
+ '--base', point_x_branch_name]
+ result = _create_pr(title, body, 'PR to merge release changes into .x branch', pr_opts)
+ print(f'PR location: {result}')
+
+
+def _create_and_push_branch_without_version_bump(version: str, branch_name: str) -> None:
+ # Usually a branch of form 1.2.x
+ # When it's a point release, it'll be any name, and then merged back into 1.2.x
+ print(f'Creating branch without version bump commit named {branch_name}...')
+ # Check if there are uncommited changes, since reset will blow them away
+
+ try:
+ msg = (f'Branch {branch_name} already exists. Delete it using '
+ f'`git branch -D {branch_name}`.')
+ _run_silent_except_error(f'git branch {branch_name}'.split(), msg)
+
+ _run_silent_except_error(f'git switch {branch_name}'.split())
+
+ # Make sure the last commit message is 'Bump version to {next version}'
+ output = _run_silent_except_error('git log -1 --pretty=%B'.split()).stdout
+ assert_msg = 'The most recent commit message should start with "Bump version to"'
+ assert output.startswith('Bump version to'), assert_msg
+
+ _run_silent_except_error('git reset --hard HEAD~1'.split())
+
+ msg = ('You shouldn\'t be trying to re-push a minor version branch. If you really want '
+ 'to, go into GitHub, turn off branch deletion protection, and delete it there. ')
+ _run_silent_except_error(f'git push origin {branch_name}'.split(), msg)
+ finally:
+ # Switching to the current branch exits 0
+ _run_silent_except_error(f'git switch candidate-{version}'.split())
+ print('Created.')
+
+
+def _check_branch_matches_version(version: str) -> None:
+ # This function assumes we're on a branch like `candidate-1.2.0` or `candidate-1.2.3`
+ # where the number after candidate should be equal to the version number
+ process = _run_silent_except_error('git branch --show'.split())
+ current_branch = process.stdout.rstrip()
+ if current_branch != f'candidate-{version}':
+ print(f'Unexpected branch name found. The current branch should be candidate-{version}.')
+ print(SKIP_SYNC_MESSAGE)
+ sys.exit(1)
+
+
+def synchronize_github_repo(version: str):
+ _check_branch_matches_version(version)
+ message = ('You have uncommitted changes that will be deleted. '
+ 'Stash your changes before rerunning this script.')
+ _run_silent_except_error('git diff --quiet HEAD'.split(), message)
+
+ _sync_candidate_from_temp_to_origin(version)
+ _create_release_pr_to_main(version)
+
+ # Check the last element of the version number to see if this is a point release
+ point_version = version.split('.')[-1]
+ point_release = point_version != '0'
+ point_x_branch_name = '.'.join(version.split('.')[:-1]) + '.x'
+ if not point_release:
+ branch_name = point_x_branch_name
+ else:
+ branch_name = f'point-candidate-{version}'
+
+ _create_and_push_branch_without_version_bump(version, branch_name)
+
+ if point_release:
+ _create_release_pr_to_minor_branch(version, branch_name, point_x_branch_name)
+
+
def generate_community_forum_post(version: str):
print('Generating announcement text for community forum post')
@@ -196,8 +357,13 @@ def generate_community_forum_post(version: str):
def main(args):
parsed_args = parse_args(args)
- version = fetch_version_number()
- promote_snaps(ALL_SNAPS, 'beta', version)
+ version = parsed_args.test_version
+ if not version:
+ version = fetch_version_number()
+ if not parsed_args.skip_snaps:
+ promote_snaps(ALL_SNAPS, 'beta', version)
+ if not parsed_args.skip_github_sync:
+ synchronize_github_repo(version)
generate_community_forum_post(version)
if __name__ == "__main__":
diff --git a/tools/requirements.txt b/tools/requirements.txt
index 8760aa8ce..2c972e6ec 100644
--- a/tools/requirements.txt
+++ b/tools/requirements.txt
@@ -90,7 +90,7 @@ matplotlib-inline==0.2.2 ; python_version >= "3.10" and python_version < "4.0"
mccabe==0.7.0 ; python_version >= "3.10" and python_version < "4.0"
mdurl==0.1.2 ; python_version >= "3.10" and python_version < "4.0"
more-itertools==11.1.0 ; python_version >= "3.10" and python_version < "4.0"
-msgpack==1.1.2 ; python_version >= "3.10" and python_version < "4.0"
+msgpack==1.2.1 ; python_version >= "3.10" and python_version < "4.0"
mypy-extensions==1.1.0 ; python_version >= "3.10" and python_version < "4.0"
mypy==1.9.0 ; python_version >= "3.10" and python_version < "4.0"
nh3==0.3.5 ; python_version >= "3.10" and python_version < "4.0"
diff --git a/tools/snap/build_remote.py b/tools/snap/build_remote.py
index 5ed9f0e05..ba6f562eb 100755
--- a/tools/snap/build_remote.py
+++ b/tools/snap/build_remote.py
@@ -144,14 +144,17 @@ def _build_snap(
for arch in archs:
snap_path_list = glob.glob(join(workspace, f'{target}_*_{arch}.snap'))
assert len(snap_path_list) == 1
- with open(snap_path_list[0], 'r') as f:
+ with open(snap_path_list[0], 'rb') as f:
+ first_block = f.read(10)
+ # 'hsqs' is the magic number that SquashFS files start with
+ if first_block.startswith(b'hsqs'):
+ continue
+ failed_archs.add(arch)
try:
- first_line = f.readline().rstrip()
+ first_block_str = first_block.decode()
except UnicodeDecodeError:
- first_line = ''
- if first_line == "":
- failed_archs.add(arch)
- print(f'The {target} {arch} snap file contains html instead of a snap')
+ first_block_str = first_block.hex(sep=',')
+ print(f'The {target} {arch} snap file began with invalid data: {first_block_str}')
dump_output = bool(failed_archs)
if not dump_output: