Compare commits
38 Commits
ubupdate
...
test-pytho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b973de36d5 | ||
|
|
8143f80478 | ||
|
|
38fc7fcc48 | ||
|
|
0e225dcba2 | ||
|
|
4ff5719a65 | ||
|
|
798a61622c | ||
|
|
b20d01e032 | ||
|
|
990352e371 | ||
|
|
c5a5d6f9a1 | ||
|
|
d4850399c5 | ||
|
|
c4be440853 | ||
|
|
165c3e32b0 | ||
|
|
2660a2017b | ||
|
|
6a6544fd90 | ||
|
|
320cf92944 | ||
|
|
3078c2f3db | ||
|
|
c54f99e35b | ||
|
|
c81dbb2582 | ||
|
|
742f97e11a | ||
|
|
84c8dbc52a | ||
|
|
4b51e3004c | ||
|
|
018800c5cc | ||
|
|
2eb4154169 | ||
|
|
becc2c3fee | ||
|
|
cb5382d4d5 | ||
|
|
6975e32998 | ||
|
|
62962357c5 | ||
|
|
343b540970 | ||
|
|
089b7efacd | ||
|
|
1584b0b58c | ||
|
|
141b15077c | ||
|
|
ee2c4844b9 | ||
|
|
181813b9b2 | ||
|
|
43d0652b0d | ||
|
|
80e68bec26 | ||
|
|
7b2b2b1685 | ||
|
|
c3c587001f | ||
|
|
281b724996 |
@@ -1,8 +1,8 @@
|
||||
# Configuring Azure Pipelines with Certbot
|
||||
|
||||
Let's begin. All pipelines are defined in `.azure-pipelines`. Currently there are two:
|
||||
* `.azure-pipelines/main.yml` is the main one, executed on PRs for master, and pushes to master,
|
||||
* `.azure-pipelines/advanced.yml` add installer testing on top of the main pipeline, and is executed for `test-*` branches, release branches, and nightly run for master.
|
||||
* `.azure-pipelines/main.yml` is the main one, executed on PRs for main, and pushes to main,
|
||||
* `.azure-pipelines/advanced.yml` add installer testing on top of the main pipeline, and is executed for `test-*` branches, release branches, and nightly run for main.
|
||||
|
||||
Several templates are defined in `.azure-pipelines/templates`. These YAML files aggregate common jobs configuration that can be reused in several pipelines.
|
||||
|
||||
@@ -64,7 +64,7 @@ Azure Pipeline needs RW on code, RO on metadata, RW on checks, commit statuses,
|
||||
RW access here is required to allow update of the pipelines YAML files from Azure DevOps interface, and to
|
||||
update the status of builds and PRs on GitHub side when Azure Pipelines are triggered.
|
||||
Note however that no admin access is defined here: this means that Azure Pipelines cannot do anything with
|
||||
protected branches, like master, and cannot modify the security context around this on GitHub.
|
||||
protected branches, like main, and cannot modify the security context around this on GitHub.
|
||||
Access can be defined for all or only selected repositories, which is nice.
|
||||
```
|
||||
|
||||
@@ -91,11 +91,11 @@ grant permissions from Azure Pipelines to GitHub in order to setup a GitHub OAut
|
||||
then are way too large (admin level on almost everything), while the classic approach does not add any more
|
||||
permissions, and works perfectly well.__
|
||||
|
||||
- Select GitHub in "Select your repository section", choose certbot/certbot in Repository, master in default branch.
|
||||
- Select GitHub in "Select your repository section", choose certbot/certbot in Repository, main in default branch.
|
||||
- Click on YAML option for "Select a template"
|
||||
- Choose a name for the pipeline (eg. test-pipeline), and browse to the actual pipeline YAML definition in the
|
||||
"YAML file path" input (eg. `.azure-pipelines/test-pipeline.yml`)
|
||||
- Click "Save & queue", choose the master branch to build the first pipeline, and click "Save and run" button.
|
||||
- Click "Save & queue", choose the main branch to build the first pipeline, and click "Save and run" button.
|
||||
|
||||
_Done. Pipeline is operational. Repeat to add more pipelines from existing YAML files in `.azure-pipelines`._
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# We run the test suite on commits to master so codecov gets coverage data
|
||||
# about the master branch and can use it to track coverage changes.
|
||||
# We run the test suite on commits to main so codecov gets coverage data
|
||||
# about the main branch and can use it to track coverage changes.
|
||||
trigger:
|
||||
- master
|
||||
- main
|
||||
pr:
|
||||
- master
|
||||
- main
|
||||
- '*.x'
|
||||
|
||||
variables:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Nightly pipeline running each day for master.
|
||||
# Nightly pipeline running each day for main.
|
||||
trigger: none
|
||||
pr: none
|
||||
schedules:
|
||||
@@ -6,7 +6,7 @@ schedules:
|
||||
displayName: Nightly build
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- main
|
||||
always: true
|
||||
|
||||
variables:
|
||||
|
||||
@@ -25,8 +25,9 @@ jobs:
|
||||
linux-integration-nginx-oldest:
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: integration-nginx-oldest
|
||||
# python 3.8 integration tests are not run here because they're run as
|
||||
# part of the standard test suite
|
||||
linux-py38-integration:
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: integration
|
||||
linux-py39-integration:
|
||||
PYTHON_VERSION: 3.9
|
||||
TOXENV: integration
|
||||
@@ -36,20 +37,19 @@ jobs:
|
||||
linux-py311-integration:
|
||||
PYTHON_VERSION: 3.11
|
||||
TOXENV: integration
|
||||
linux-py312-integration:
|
||||
PYTHON_VERSION: 3.12
|
||||
TOXENV: integration
|
||||
# python 3.12 integration tests are not run here because they're run as
|
||||
# part of the standard test suite
|
||||
nginx-compat:
|
||||
TOXENV: nginx_compat
|
||||
linux-integration-rfc2136:
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
PYTHON_VERSION: 3.8
|
||||
PYTHON_VERSION: 3.12
|
||||
TOXENV: integration-dns-rfc2136
|
||||
le-modification:
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
TOXENV: modification
|
||||
farmtest-apache2:
|
||||
PYTHON_VERSION: 3.8
|
||||
PYTHON_VERSION: 3.12
|
||||
TOXENV: test-farm-apache2
|
||||
pool:
|
||||
vmImage: $(IMAGE_NAME)
|
||||
|
||||
@@ -1,60 +1,4 @@
|
||||
jobs:
|
||||
- job: docker_build
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
arm32v6:
|
||||
DOCKER_ARCH: arm32v6
|
||||
arm64v8:
|
||||
DOCKER_ARCH: arm64v8
|
||||
amd64:
|
||||
DOCKER_ARCH: amd64
|
||||
# The default timeout of 60 minutes is a little low for compiling
|
||||
# cryptography on ARM architectures.
|
||||
timeoutInMinutes: 180
|
||||
steps:
|
||||
- bash: set -e && tools/docker/build.sh $(dockerTag) $DOCKER_ARCH
|
||||
displayName: Build the Docker images
|
||||
# We don't filter for the Docker Hub organization to continue to allow
|
||||
# easy testing of these scripts on forks.
|
||||
- bash: |
|
||||
set -e
|
||||
DOCKER_IMAGES=$(docker images --filter reference='*/certbot' --filter reference='*/dns-*' --format '{{.Repository}}')
|
||||
docker save --output images.tar $DOCKER_IMAGES
|
||||
displayName: Save the Docker images
|
||||
# If the name of the tar file or artifact changes, the deploy stage will
|
||||
# also need to be updated.
|
||||
- bash: set -e && mv images.tar $(Build.ArtifactStagingDirectory)
|
||||
displayName: Prepare Docker artifact
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
path: $(Build.ArtifactStagingDirectory)
|
||||
artifact: docker_$(DOCKER_ARCH)
|
||||
displayName: Store Docker artifact
|
||||
- job: docker_test
|
||||
dependsOn: docker_build
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
arm32v6:
|
||||
DOCKER_ARCH: arm32v6
|
||||
arm64v8:
|
||||
DOCKER_ARCH: arm64v8
|
||||
amd64:
|
||||
DOCKER_ARCH: amd64
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: docker_$(DOCKER_ARCH)
|
||||
path: $(Build.SourcesDirectory)
|
||||
displayName: Retrieve Docker images
|
||||
- bash: set -e && docker load --input $(Build.SourcesDirectory)/images.tar
|
||||
displayName: Load Docker images
|
||||
- bash: |
|
||||
set -e && tools/docker/test.sh $(dockerTag) $DOCKER_ARCH
|
||||
displayName: Run integration tests for Docker images
|
||||
- job: snaps_build
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
@@ -62,10 +6,6 @@ jobs:
|
||||
matrix:
|
||||
amd64:
|
||||
SNAP_ARCH: amd64
|
||||
armhf:
|
||||
SNAP_ARCH: armhf
|
||||
arm64:
|
||||
SNAP_ARCH: arm64
|
||||
timeoutInMinutes: 0
|
||||
steps:
|
||||
- script: |
|
||||
@@ -76,7 +16,7 @@ jobs:
|
||||
displayName: Install dependencies
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: 3.8
|
||||
versionSpec: 3.12
|
||||
addToPath: true
|
||||
- task: DownloadSecureFile@1
|
||||
name: credentials
|
||||
@@ -88,12 +28,11 @@ jobs:
|
||||
git config --global user.name "$(Build.RequestedFor)"
|
||||
mkdir -p ~/.local/share/snapcraft/provider/launchpad
|
||||
cp $(credentials.secureFilePath) ~/.local/share/snapcraft/provider/launchpad/credentials
|
||||
python3 tools/snap/build_remote.py ALL --archs ${SNAP_ARCH} --timeout $(snapBuildTimeout)
|
||||
python3 tools/snap/build_remote.py certbot --archs ${SNAP_ARCH} --timeout $(snapBuildTimeout)
|
||||
displayName: Build snaps
|
||||
- script: |
|
||||
set -e
|
||||
mv *.snap $(Build.ArtifactStagingDirectory)
|
||||
mv certbot-dns-*/*.snap $(Build.ArtifactStagingDirectory)
|
||||
displayName: Prepare artifacts
|
||||
- task: PublishPipelineArtifact@1
|
||||
inputs:
|
||||
@@ -107,7 +46,7 @@ jobs:
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: 3.8
|
||||
versionSpec: 3.12
|
||||
addToPath: true
|
||||
- script: |
|
||||
set -e
|
||||
@@ -129,31 +68,3 @@ jobs:
|
||||
set -e
|
||||
venv/bin/python -m tox run -e integration-external,apacheconftest-external-with-pebble
|
||||
displayName: Run tox
|
||||
- job: snap_dns_run
|
||||
dependsOn: snaps_build
|
||||
pool:
|
||||
vmImage: ubuntu-22.04
|
||||
steps:
|
||||
- script: |
|
||||
set -e
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends snapd
|
||||
displayName: Install dependencies
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: 3.8
|
||||
addToPath: true
|
||||
- task: DownloadPipelineArtifact@2
|
||||
inputs:
|
||||
artifact: snaps_amd64
|
||||
path: $(Build.SourcesDirectory)/snap
|
||||
displayName: Retrieve Certbot snaps
|
||||
- script: |
|
||||
set -e
|
||||
python3 -m venv venv
|
||||
venv/bin/python tools/pip_install.py -e certbot-ci
|
||||
displayName: Prepare Certbot-CI
|
||||
- script: |
|
||||
set -e
|
||||
sudo -E venv/bin/pytest certbot-ci/snap_integration_tests/dns_tests --allow-persistent-changes --snap-folder $(Build.SourcesDirectory)/snap --snap-arch amd64
|
||||
displayName: Test DNS plugins snaps
|
||||
|
||||
@@ -5,14 +5,16 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
macos-py38-cover:
|
||||
IMAGE_NAME: macOS-12
|
||||
# mac unit+cover tests with the oldest python we support
|
||||
IMAGE_NAME: macOS-15
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: cover
|
||||
# As of pip 23.1.0, builds started failing on macOS unless this flag was set.
|
||||
# See https://github.com/certbot/certbot/pull/9717#issuecomment-1610861794.
|
||||
PIP_USE_PEP517: "true"
|
||||
macos-cover:
|
||||
IMAGE_NAME: macOS-13
|
||||
# mac unit+cover tests with the newest python we support
|
||||
IMAGE_NAME: macOS-15
|
||||
TOXENV: cover
|
||||
# See explanation under macos-py38-cover.
|
||||
PIP_USE_PEP517: "true"
|
||||
@@ -21,10 +23,12 @@ jobs:
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: oldest
|
||||
linux-py38:
|
||||
# linux unit tests with the oldest python we support
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: py38
|
||||
linux-cover:
|
||||
# linux unit+cover tests with the newest python we support
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
TOXENV: cover
|
||||
linux-lint:
|
||||
@@ -35,7 +39,6 @@ jobs:
|
||||
TOXENV: mypy
|
||||
linux-integration:
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
PYTHON_VERSION: 3.8
|
||||
TOXENV: integration
|
||||
apache-compat:
|
||||
IMAGE_NAME: ubuntu-22.04
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
stages:
|
||||
- stage: TestAndPackage
|
||||
jobs:
|
||||
- template: ../jobs/standard-tests-jobs.yml
|
||||
- template: ../jobs/extended-tests-jobs.yml
|
||||
- template: ../jobs/packaging-jobs.yml
|
||||
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -1,6 +1,6 @@
|
||||
## 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 the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), edit the `master` section of `certbot/CHANGELOG.md` to include a description of the change being made.
|
||||
- [ ] If the change being made is to a [distributed component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout), edit the `main` section of `certbot/CHANGELOG.md` to include a description of the change being made.
|
||||
- [ ] Add or update any documentation as needed to support the changes in this PR.
|
||||
- [ ] Include your name in `AUTHORS.md` if you like.
|
||||
|
||||
25
.github/workflows/merged.yaml
vendored
25
.github/workflows/merged.yaml
vendored
@@ -8,25 +8,14 @@ on:
|
||||
jobs:
|
||||
if_merged:
|
||||
# Forked repos can not access Mattermost secret.
|
||||
if: github.event.pull_request.merged == true && !github.event.pull_request.head.repo.fork
|
||||
if: github.event.pull_request.merged == true && !github.event.pull_request.head.repo.fork
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create Mattermost Message
|
||||
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#example-of-a-script-injection-attack
|
||||
env:
|
||||
NUMBER: ${{ github.event.number }}
|
||||
PR_URL: https://github.com/${{ github.repository }}/pull/${{ github.event.number }}
|
||||
REPO: ${{ github.repository }}
|
||||
USER: ${{ github.actor }}
|
||||
TITLE: ${{ github.event.pull_request.title }}
|
||||
run: |
|
||||
jq --null-input \
|
||||
--arg number "$NUMBER" \
|
||||
--arg pr_url "$PR_URL" \
|
||||
--arg repo "$REPO" \
|
||||
--arg user "$USER" \
|
||||
--arg title "$TITLE" \
|
||||
'{ "text": "[\($repo)] | [\($title) #\($number)](\($pr_url)) was merged into master by \($user)" }' > mattermost.json
|
||||
- uses: mattermost/action-mattermost-notify@master
|
||||
env:
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_MERGE_WEBHOOK }}
|
||||
TEXT: >
|
||||
[${{ github.repository }}] |
|
||||
[${{ github.event.pull_request.title }}
|
||||
#${{ github.event.number }}](https://github.com/${{ github.repository }}/pull/${{ github.event.number }})
|
||||
was merged into main by ${{ github.actor }}
|
||||
|
||||
22
.github/workflows/notify_weekly.yaml
vendored
22
.github/workflows/notify_weekly.yaml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
schedule:
|
||||
# Every week on Thursday @ 13:00
|
||||
- cron: "0 13 * * 4"
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
send-mattermost-message:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -11,15 +12,16 @@ jobs:
|
||||
steps:
|
||||
- name: Create Mattermost Message
|
||||
run: |
|
||||
DATE=$(date --date="7 days ago" +"%Y-%m-%d")
|
||||
MERGED_URL="https://github.com/pulls?q=merged%3A%3E${DATE}+org%3Acertbot"
|
||||
UPDATED_URL="https://github.com/pulls?q=updated%3A%3E${DATE}+org%3Acertbot"
|
||||
echo "{\"text\":\"## Updates Across Certbot Repos\n\n
|
||||
- Certbot team members SHOULD look at: [link]($MERGED_URL)\n\n
|
||||
- Certbot team members MAY also want to look at: [link]($UPDATED_URL)\n\n
|
||||
- Want to Discuss something today? Place it [here](https://docs.google.com/document/d/17YMUbtC1yg6MfiTMwT8zVm9LmO-cuGVBom0qFn8XJBM/edit?usp=sharing) and we can meet today on Zoom.\n\n
|
||||
- The key words SHOULD and MAY in this message are to be interpreted as described in [RFC 8147](https://www.rfc-editor.org/rfc/rfc8174). \"
|
||||
}" > mattermost.json
|
||||
DATE=$(date --date="7 days ago" +"%Y-%m-%d")
|
||||
echo "MERGED_URL=https://github.com/pulls?q=merged%3A%3E${DATE}+org%3Acertbot" >> $GITHUB_ENV
|
||||
echo "UPDATED_URL=https://github.com/pulls?q=updated%3A%3E${DATE}+org%3Acertbot" >> $GITHUB_ENV
|
||||
- uses: mattermost/action-mattermost-notify@master
|
||||
env:
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK_URL }}
|
||||
MATTERMOST_CHANNEL: private-certbot
|
||||
TEXT: |
|
||||
## Updates Across Certbot Repos
|
||||
- Certbot team members SHOULD look at: [link](${{ env.MERGED_URL }})
|
||||
- Certbot team members MAY also want to look at: [link](${{ env.UPDATED_URL }})
|
||||
- Want to Discuss something today? Place it [here](https://docs.google.com/document/d/17YMUbtC1yg6MfiTMwT8zVm9LmO-cuGVBom0qFn8XJBM/edit?usp=sharing) and we can meet today on Zoom.
|
||||
- The key words SHOULD and MAY in this message are to be interpreted as described in [RFC 8147](https://www.rfc-editor.org/rfc/rfc8174).
|
||||
|
||||
1
.github/workflows/stale.yml
vendored
1
.github/workflows/stale.yml
vendored
@@ -3,6 +3,7 @@ on:
|
||||
schedule:
|
||||
# Run 1:24AM every night
|
||||
- cron: '24 1 * * *'
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
issues: write
|
||||
jobs:
|
||||
|
||||
@@ -6,6 +6,7 @@ This module is an implementation of the `ACME protocol`_.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
# This code exists to keep backwards compatibility with people using acme.jose
|
||||
# before it became the standalone josepy package.
|
||||
@@ -19,3 +20,10 @@ for mod in list(sys.modules):
|
||||
# preserved (acme.jose.* is josepy.*)
|
||||
if mod == 'josepy' or mod.startswith('josepy.'):
|
||||
sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = sys.modules[mod]
|
||||
|
||||
if sys.version_info[:2] == (3, 8):
|
||||
warnings.warn(
|
||||
"Python 3.8 support will be dropped in the next planned release of "
|
||||
"acme. Please upgrade your Python version.",
|
||||
PendingDeprecationWarning,
|
||||
) # pragma: no cover
|
||||
|
||||
@@ -3,11 +3,13 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'cryptography>=3.2.1',
|
||||
'josepy>=1.13.0',
|
||||
# Josepy 2+ may introduce backward incompatible changes by droping usage of
|
||||
# deprecated PyOpenSSL APIs.
|
||||
'josepy>=1.13.0, <2',
|
||||
# pyOpenSSL 23.1.0 is a bad release: https://github.com/pyca/pyopenssl/issues/1199
|
||||
'PyOpenSSL>=17.5.0,!=23.1.0',
|
||||
'pyrfc3339',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
|
||||
@@ -96,7 +96,6 @@ def _prepare_args_env(certbot_args: List[str], directory_url: str, http_01_port:
|
||||
'--no-verify-ssl',
|
||||
'--http-01-port', str(http_01_port),
|
||||
'--https-port', str(tls_alpn_01_port),
|
||||
'--manual-public-ip-logging-ok',
|
||||
'--config-dir', config_dir,
|
||||
'--work-dir', os.path.join(workspace, 'work'),
|
||||
'--logs-dir', os.path.join(workspace, 'logs'),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'certbot',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
# for now, do not upgrade to cloudflare>=2.20 to avoid deprecation warnings and the breaking
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'python-digitalocean>=1.11', # 1.15.0 or newer is recommended for TTL support
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
# This version of lexicon is required to address the problem described in
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'google-api-python-client>=1.6.5',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.15.1',
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dnspython>=1.15.0',
|
||||
|
||||
@@ -101,13 +101,4 @@ Examples
|
||||
--dns-route53 \\
|
||||
-d example.com \\
|
||||
-d www.example.com
|
||||
|
||||
.. code-block:: bash
|
||||
:caption: To acquire a certificate for ``example.com``, waiting 30 seconds
|
||||
for DNS propagation
|
||||
|
||||
certbot certonly \\
|
||||
--dns-route53 \\
|
||||
--dns-route53-propagation-seconds 30 \\
|
||||
-d example.com
|
||||
"""
|
||||
|
||||
@@ -6,18 +6,20 @@ from typing import Any
|
||||
from typing import Callable
|
||||
from typing import DefaultDict
|
||||
from typing import Dict
|
||||
from typing import Iterable
|
||||
from typing import List
|
||||
from typing import Type
|
||||
|
||||
import boto3
|
||||
from botocore.exceptions import ClientError
|
||||
from botocore.exceptions import NoCredentialsError
|
||||
|
||||
from acme.challenges import ChallengeResponse
|
||||
from acme import challenges
|
||||
from certbot import achallenges
|
||||
from certbot import errors
|
||||
from certbot import interfaces
|
||||
from certbot.achallenges import AnnotatedChallenge
|
||||
from certbot.plugins import dns_common
|
||||
from certbot.util import add_deprecated_argument
|
||||
from certbot.plugins import common
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -27,7 +29,7 @@ INSTRUCTIONS = (
|
||||
"and add the necessary permissions for Route53 access.")
|
||||
|
||||
|
||||
class Authenticator(dns_common.DNSAuthenticator):
|
||||
class Authenticator(common.Plugin, interfaces.Authenticator):
|
||||
"""Route53 Authenticator
|
||||
|
||||
This authenticator solves a DNS01 challenge by uploading the answer to AWS
|
||||
@@ -41,6 +43,7 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.r53 = boto3.client("route53")
|
||||
self._attempt_cleanup = False
|
||||
self._resource_records: DefaultDict[str, List[Dict[str, str]]] = \
|
||||
collections.defaultdict(list)
|
||||
|
||||
@@ -48,9 +51,9 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
return "Solve a DNS01 challenge using AWS Route53"
|
||||
|
||||
@classmethod
|
||||
def add_parser_arguments(cls, add: Callable[..., None], # pylint: disable=arguments-differ
|
||||
default_propagation_seconds: int = 10) -> None:
|
||||
add_deprecated_argument(add, 'propagation-seconds', 1)
|
||||
def add_parser_arguments(cls, add: Callable[..., None]) -> None:
|
||||
# This authenticator currently adds no extra arguments.
|
||||
pass
|
||||
|
||||
def auth_hint(self, failed_achalls: List[achallenges.AnnotatedChallenge]) -> str:
|
||||
return (
|
||||
@@ -58,13 +61,13 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
'--dns-route53. Ensure the above domains have their DNS hosted by AWS Route53.'
|
||||
)
|
||||
|
||||
def _setup_credentials(self) -> None:
|
||||
def prepare(self) -> None:
|
||||
pass
|
||||
|
||||
def _perform(self, domain: str, validation_name: str, validation: str) -> None:
|
||||
pass
|
||||
def get_chall_pref(self, unused_domain: str) -> Iterable[Type[challenges.Challenge]]:
|
||||
return [challenges.DNS01]
|
||||
|
||||
def perform(self, achalls: List[AnnotatedChallenge]) -> List[ChallengeResponse]:
|
||||
def perform(self, achalls: List[AnnotatedChallenge]) -> List[challenges.ChallengeResponse]:
|
||||
self._attempt_cleanup = True
|
||||
|
||||
try:
|
||||
@@ -82,7 +85,16 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
raise errors.PluginError("\n".join([str(e), INSTRUCTIONS]))
|
||||
return [achall.response(achall.account_key) for achall in achalls]
|
||||
|
||||
def _cleanup(self, domain: str, validation_name: str, validation: str) -> None:
|
||||
def cleanup(self, achalls: List[achallenges.AnnotatedChallenge]) -> None:
|
||||
if self._attempt_cleanup:
|
||||
for achall in achalls:
|
||||
domain = achall.domain
|
||||
validation_domain_name = achall.validation_domain_name(domain)
|
||||
validation = achall.validation(achall.account_key)
|
||||
|
||||
self._cleanup(validation_domain_name, validation)
|
||||
|
||||
def _cleanup(self, validation_name: str, validation: str) -> None:
|
||||
try:
|
||||
self._change_txt_record("DELETE", validation_name, validation)
|
||||
except (NoCredentialsError, ClientError) as e:
|
||||
@@ -166,3 +178,13 @@ class Authenticator(dns_common.DNSAuthenticator):
|
||||
raise errors.PluginError(
|
||||
"Timed out waiting for Route53 change. Current status: %s" %
|
||||
response["ChangeInfo"]["Status"])
|
||||
|
||||
|
||||
# Our route53 plugin was initially a 3rd party plugin named `certbot-route53:auth` as described at
|
||||
# https://github.com/certbot/certbot/issues/4688. This shim exists to allow installations using the
|
||||
# old plugin name of `certbot-route53:auth` to continue to work without cluttering things like
|
||||
# Certbot's help output with two route53 plugins.
|
||||
class HiddenAuthenticator(Authenticator):
|
||||
"""A hidden shim around certbot-dns-route53 for backwards compatibility."""
|
||||
|
||||
hidden = True
|
||||
|
||||
@@ -6,17 +6,27 @@ from unittest import mock
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from botocore.exceptions import NoCredentialsError
|
||||
import josepy as jose
|
||||
import pytest
|
||||
|
||||
from acme import challenges
|
||||
from certbot import achallenges
|
||||
from certbot import errors
|
||||
from certbot.compat import os
|
||||
from certbot.plugins import dns_test_common
|
||||
from certbot.plugins.dns_test_common import DOMAIN
|
||||
from certbot.tests import acme_util
|
||||
from certbot.tests import util as test_util
|
||||
|
||||
DOMAIN = 'example.com'
|
||||
KEY = jose.JWKRSA.load(test_util.load_vector("rsa512_key.pem"))
|
||||
|
||||
|
||||
class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest):
|
||||
class AuthenticatorTest(unittest.TestCase):
|
||||
# pylint: disable=protected-access
|
||||
|
||||
achall = achallenges.KeyAuthorizationAnnotatedChallenge(
|
||||
challb=acme_util.DNS01, domain=DOMAIN, account_key=KEY)
|
||||
|
||||
def setUp(self):
|
||||
from certbot_dns_route53._internal.dns_route53 import Authenticator
|
||||
|
||||
@@ -35,6 +45,12 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest
|
||||
del os.environ["AWS_ACCESS_KEY_ID"]
|
||||
del os.environ["AWS_SECRET_ACCESS_KEY"]
|
||||
|
||||
def test_more_info(self) -> None:
|
||||
self.assertTrue(isinstance(self.auth.more_info(), str))
|
||||
|
||||
def test_get_chall_pref(self) -> None:
|
||||
self.assertEqual(self.auth.get_chall_pref("example.org"), [challenges.DNS01])
|
||||
|
||||
def test_perform(self):
|
||||
self.auth._change_txt_record = mock.MagicMock()
|
||||
self.auth._wait_for_change = mock.MagicMock()
|
||||
@@ -85,13 +101,6 @@ class AuthenticatorTest(unittest.TestCase, dns_test_common.BaseAuthenticatorTest
|
||||
|
||||
self.auth.cleanup([self.achall])
|
||||
|
||||
def test_parser_arguments(self) -> None:
|
||||
from certbot.util import DeprecatedArgumentAction
|
||||
m = mock.MagicMock()
|
||||
self.auth.add_parser_arguments(m) # pylint: disable=no-member
|
||||
m.assert_any_call('propagation-seconds', action=DeprecatedArgumentAction,
|
||||
help=mock.ANY, nargs=1)
|
||||
|
||||
|
||||
class ClientTest(unittest.TestCase):
|
||||
# pylint: disable=protected-access
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
"""Shim around `~certbot_dns_route53._internal.dns_route53` for backwards compatibility."""
|
||||
from typing import Any
|
||||
import warnings
|
||||
|
||||
from certbot_dns_route53._internal import dns_route53
|
||||
|
||||
|
||||
class Authenticator(dns_route53.Authenticator):
|
||||
"""Shim around `~certbot_dns_route53._internal.dns_route53.Authenticator`
|
||||
for backwards compatibility."""
|
||||
|
||||
hidden = True
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
warnings.warn("The 'authenticator' module was renamed 'dns_route53'",
|
||||
DeprecationWarning)
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'boto3>=1.15.15',
|
||||
@@ -71,7 +71,7 @@ setup(
|
||||
entry_points={
|
||||
'certbot.plugins': [
|
||||
'dns-route53 = certbot_dns_route53._internal.dns_route53:Authenticator',
|
||||
'certbot-route53:auth = certbot_dns_route53.authenticator:Authenticator'
|
||||
'certbot-route53:auth = certbot_dns_route53._internal.dns_route53:HiddenAuthenticator',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
'dns-lexicon>=3.14.1',
|
||||
|
||||
@@ -294,7 +294,7 @@ def dumps(blocks: UnspacedList) -> str:
|
||||
"""Dump to a Unicode string.
|
||||
|
||||
:param UnspacedList blocks: The parsed tree
|
||||
:rtype: six.text_type
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
return str(RawNginxDumper(blocks.spaced))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from setuptools import find_packages
|
||||
from setuptools import setup
|
||||
|
||||
version = '2.12.0.dev0'
|
||||
version = '3.1.0.dev0'
|
||||
|
||||
install_requires = [
|
||||
# We specify the minimum acme and certbot version as the current plugin
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
|
||||
# Certbot change log
|
||||
|
||||
Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## 2.12.0 - master
|
||||
## 3.1.0 - main
|
||||
|
||||
### Added
|
||||
|
||||
@@ -18,6 +19,31 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
More details about these changes can be found on our GitHub repo.
|
||||
|
||||
## 3.0.0 - 2024-11-05
|
||||
|
||||
### Added
|
||||
|
||||
*
|
||||
|
||||
### Changed
|
||||
|
||||
* The update_symlinks command was removed.
|
||||
* The `csr_dir` and `key_dir` attributes on
|
||||
`certbot.configuration.NamespaceConfig` were removed.
|
||||
* The `--manual-public-ip-logging-ok` command line flag was removed.
|
||||
* The `--dns-route53-propagation-seconds` command line flag was removed.
|
||||
* The `certbot_dns_route53.authenticator` module has been removed. This should
|
||||
not affect any users of the plugin and instead would only affect developers
|
||||
trying to develop on top of the old code.
|
||||
* Support for Python 3.8 was deprecated and will be removed in our next planned
|
||||
release.
|
||||
|
||||
### Fixed
|
||||
|
||||
*
|
||||
|
||||
More details about these changes can be found on our GitHub repo.
|
||||
|
||||
## 2.11.0 - 2024-06-05
|
||||
|
||||
### Added
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
|build-status|
|
||||
|
||||
.. |build-status| image:: https://img.shields.io/azure-devops/build/certbot/ba534f81-a483-4b9b-9b4e-a60bec8fee72/5/master
|
||||
.. |build-status| image:: https://img.shields.io/azure-devops/build/certbot/ba534f81-a483-4b9b-9b4e-a60bec8fee72/5/main
|
||||
:target: https://dev.azure.com/certbot/certbot/_build?definitionId=5
|
||||
:alt: Azure Pipelines CI status
|
||||
|
||||
|
||||
.. image:: https://raw.githubusercontent.com/EFForg/design/master/logos/eff-certbot-lockup.png
|
||||
:width: 200
|
||||
:alt: EFF Certbot Logo
|
||||
@@ -39,7 +39,7 @@ Documentation: https://certbot.eff.org/docs
|
||||
|
||||
Software project: https://github.com/certbot/certbot
|
||||
|
||||
Changelog: https://github.com/certbot/certbot/blob/master/certbot/CHANGELOG.md
|
||||
Changelog: https://github.com/certbot/certbot/blob/main/certbot/CHANGELOG.md
|
||||
|
||||
For Contributors: https://certbot.eff.org/docs/contributing.html
|
||||
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
"""Certbot client."""
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
# version number like 1.2.3a0, must have at least 2 parts, like 1.2
|
||||
__version__ = '2.12.0.dev0'
|
||||
__version__ = '3.1.0.dev0'
|
||||
|
||||
if sys.version_info[:2] == (3, 8):
|
||||
warnings.warn(
|
||||
"Python 3.8 support will be dropped in the next planned release of "
|
||||
"certbot. Please upgrade your Python version.",
|
||||
PendingDeprecationWarning,
|
||||
) # pragma: no cover
|
||||
|
||||
@@ -30,22 +30,6 @@ logger = logging.getLogger(__name__)
|
||||
###################
|
||||
|
||||
|
||||
def update_live_symlinks(config: configuration.NamespaceConfig) -> None:
|
||||
"""Update the certificate file family symlinks to use archive_dir.
|
||||
|
||||
Use the information in the config file to make symlinks point to
|
||||
the correct archive directory.
|
||||
|
||||
.. note:: This assumes that the installation is using a Reverter object.
|
||||
|
||||
:param config: Configuration.
|
||||
:type config: :class:`certbot._internal.configuration.NamespaceConfig`
|
||||
|
||||
"""
|
||||
for renewal_file in storage.renewal_conf_files(config):
|
||||
storage.RenewableCert(renewal_file, config, update_symlinks=True)
|
||||
|
||||
|
||||
def rename_lineage(config: configuration.NamespaceConfig) -> None:
|
||||
"""Rename the specified lineage to the new name.
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ class HelpfulArgumentParser:
|
||||
"revoke": main.revoke,
|
||||
"rollback": main.rollback,
|
||||
"everything": main.run,
|
||||
"update_symlinks": main.update_symlinks,
|
||||
"certificates": main.certificates,
|
||||
"delete": main.delete,
|
||||
"enhance": main.enhance,
|
||||
|
||||
@@ -182,9 +182,6 @@ BACKUP_DIR = "backups"
|
||||
"""Directory (relative to `certbot.configuration.NamespaceConfig.work_dir`)
|
||||
where backups are kept."""
|
||||
|
||||
CSR_DIR = "csr"
|
||||
"""See `certbot.configuration.NamespaceConfig.csr_dir`."""
|
||||
|
||||
IN_PROGRESS_DIR = "IN_PROGRESS"
|
||||
"""Directory used before a permanent checkpoint is finalized (relative to
|
||||
`certbot.configuration.NamespaceConfig.work_dir`)."""
|
||||
|
||||
@@ -15,7 +15,6 @@ from typing import Optional
|
||||
from typing import Tuple
|
||||
from typing import TypeVar
|
||||
from typing import Union
|
||||
import warnings
|
||||
|
||||
import configobj
|
||||
import josepy as jose
|
||||
@@ -1266,27 +1265,6 @@ def rollback(config: configuration.NamespaceConfig, plugins: plugins_disco.Plugi
|
||||
client.rollback(config.installer, config.checkpoints, config, plugins)
|
||||
|
||||
|
||||
def update_symlinks(config: configuration.NamespaceConfig,
|
||||
unused_plugins: plugins_disco.PluginsRegistry) -> None:
|
||||
"""Update the certificate file family symlinks
|
||||
|
||||
Use the information in the config file to make symlinks point to
|
||||
the correct archive directory.
|
||||
|
||||
:param config: Configuration object
|
||||
:type config: configuration.NamespaceConfig
|
||||
|
||||
:param unused_plugins: List of plugins (deprecated)
|
||||
:type unused_plugins: plugins_disco.PluginsRegistry
|
||||
|
||||
:returns: `None`
|
||||
:rtype: None
|
||||
|
||||
"""
|
||||
warnings.warn("update_symlinks is deprecated and will be removed", PendingDeprecationWarning)
|
||||
cert_manager.update_live_symlinks(config)
|
||||
|
||||
|
||||
def rename(config: configuration.NamespaceConfig,
|
||||
unused_plugins: plugins_disco.PluginsRegistry) -> None:
|
||||
"""Rename a certificate
|
||||
@@ -1888,6 +1866,10 @@ def main(cli_args: Optional[List[str]] = None) -> Optional[Union[str, int]]:
|
||||
if config.func != plugins_cmd: # pylint: disable=comparison-with-callable
|
||||
raise
|
||||
|
||||
if sys.version_info[:2] == (3, 8):
|
||||
logger.warning("Python 3.8 support will be dropped in the next planned release "
|
||||
"of Certbot - please upgrade your Python version.")
|
||||
|
||||
with make_displayer(config) as displayer:
|
||||
display_obj.set_display(displayer)
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ permitted by DNS standards.)
|
||||
help='Path or command to execute for the authentication script')
|
||||
add('cleanup-hook',
|
||||
help='Path or command to execute for the cleanup script')
|
||||
util.add_deprecated_argument(add, 'public-ip-logging-ok', 0)
|
||||
|
||||
def prepare(self) -> None: # pylint: disable=missing-function-docstring
|
||||
if self.config.noninteractive_mode and not self.conf('auth-hook'):
|
||||
|
||||
@@ -33,6 +33,7 @@ _ARCH_TRIPLET_MAP = {
|
||||
'amd64': 'x86_64-linux-gnu',
|
||||
's390x': 's390x-linux-gnu',
|
||||
}
|
||||
CURRENT_PYTHON_VERSION_STRING = 'python3.12'
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -71,10 +72,35 @@ def prepare_env(cli_args: List[str]) -> List[str]:
|
||||
raise e
|
||||
|
||||
data = response.json()
|
||||
connections = ['/snap/{0}/current/lib/python3.8/site-packages/'.format(item['slot']['snap'])
|
||||
for item in data.get('result', {}).get('established', [])
|
||||
if item.get('plug', {}).get('plug') == 'plugin'
|
||||
and item.get('plug-attrs', {}).get('content') == 'certbot-1']
|
||||
connections = []
|
||||
outdated_plugins = []
|
||||
for plugin in data.get('result', {}).get('established', []):
|
||||
plug: str = plugin.get('plug', {}).get('plug')
|
||||
plug_content: str = plugin.get('plug-attrs', {}).get('content')
|
||||
if plug == 'plugin' and plug_content == 'certbot-1':
|
||||
plugin_name: str = plugin['slot']['snap']
|
||||
# First, check that the plugin is using our expected python version,
|
||||
# i.e. its "read" slot is something like
|
||||
# "$SNAP/lib/python3.12/site-packages". If not, skip it and print an
|
||||
# error.
|
||||
slot_read: str = plugin.get('slot-attrs', {}).get('read', [])
|
||||
if len(slot_read) != 0 and CURRENT_PYTHON_VERSION_STRING not in slot_read[0]:
|
||||
outdated_plugins.append(plugin_name)
|
||||
continue
|
||||
|
||||
connections.append('/snap/{0}/current/lib/{1}/site-packages/'.format(
|
||||
plugin_name,
|
||||
CURRENT_PYTHON_VERSION_STRING
|
||||
))
|
||||
|
||||
if outdated_plugins:
|
||||
LOGGER.warning('The following plugins are using an outdated python version and must be '
|
||||
'updated to be compatible with Certbot 3.0. Please see '
|
||||
'https://community.letsencrypt.org/t/'
|
||||
'certbot-3-0-could-have-potential-third-party-snap-breakages/226940 '
|
||||
'for more information:')
|
||||
plugin_list = '\n'.join(' * {}'.format(plugin) for plugin in outdated_plugins)
|
||||
LOGGER.warning(plugin_list)
|
||||
|
||||
os.environ['CERTBOT_PLUGIN_PATH'] = ':'.join(connections)
|
||||
|
||||
|
||||
@@ -455,8 +455,7 @@ class RenewableCert(interfaces.RenewableCert):
|
||||
renewal configuration file and/or systemwide defaults.
|
||||
|
||||
"""
|
||||
def __init__(self, config_filename: str, cli_config: configuration.NamespaceConfig,
|
||||
update_symlinks: bool = False) -> None:
|
||||
def __init__(self, config_filename: str, cli_config: configuration.NamespaceConfig) -> None:
|
||||
"""Instantiate a RenewableCert object from an existing lineage.
|
||||
|
||||
:param str config_filename: the path to the renewal config file
|
||||
@@ -505,8 +504,6 @@ class RenewableCert(interfaces.RenewableCert):
|
||||
self.live_dir = os.path.dirname(self.cert)
|
||||
|
||||
self._fix_symlinks()
|
||||
if update_symlinks:
|
||||
self._update_symlinks()
|
||||
self._check_symlinks()
|
||||
|
||||
@property
|
||||
@@ -593,17 +590,6 @@ class RenewableCert(interfaces.RenewableCert):
|
||||
raise errors.CertStorageError("target {0} of symlink {1} does "
|
||||
"not exist".format(target, link))
|
||||
|
||||
def _update_symlinks(self) -> None:
|
||||
"""Updates symlinks to use archive_dir"""
|
||||
for kind in ALL_FOUR:
|
||||
link = getattr(self, kind)
|
||||
previous_link = get_link_target(link)
|
||||
new_link = os.path.join(self.relative_archive_dir(link),
|
||||
os.path.basename(previous_link))
|
||||
|
||||
os.unlink(link)
|
||||
os.symlink(new_link, link)
|
||||
|
||||
def _consistent(self) -> bool:
|
||||
"""Are the files associated with this lineage self-consistent?
|
||||
|
||||
@@ -636,10 +622,7 @@ class RenewableCert(interfaces.RenewableCert):
|
||||
"cert lineage's directory within the "
|
||||
"official archive directory. Link: %s, "
|
||||
"target directory: %s, "
|
||||
"archive directory: %s. If you've specified "
|
||||
"the archive directory in the renewal configuration "
|
||||
"file, you may need to update links by running "
|
||||
"certbot update_symlinks.",
|
||||
"archive directory: %s.",
|
||||
link, os.path.dirname(target), self.archive_dir)
|
||||
return False
|
||||
|
||||
|
||||
@@ -65,44 +65,6 @@ class BaseCertManagerTest(test_util.ConfigTestCase):
|
||||
return config_file
|
||||
|
||||
|
||||
class UpdateLiveSymlinksTest(BaseCertManagerTest):
|
||||
"""Tests for certbot._internal.cert_manager.update_live_symlinks
|
||||
"""
|
||||
def test_update_live_symlinks(self):
|
||||
"""Test update_live_symlinks"""
|
||||
# create files with incorrect symlinks
|
||||
from certbot._internal import cert_manager
|
||||
archive_paths = {}
|
||||
for domain in self.domains:
|
||||
custom_archive = self.domains[domain]
|
||||
if custom_archive is not None:
|
||||
archive_dir_path = custom_archive
|
||||
else:
|
||||
archive_dir_path = os.path.join(self.config.default_archive_dir, domain)
|
||||
archive_paths[domain] = {kind:
|
||||
os.path.join(archive_dir_path, kind + "1.pem") for kind in ALL_FOUR}
|
||||
for kind in ALL_FOUR:
|
||||
live_path = self.config_files[domain][kind]
|
||||
archive_path = archive_paths[domain][kind]
|
||||
open(archive_path, 'a').close()
|
||||
# path is incorrect but base must be correct
|
||||
os.symlink(os.path.join(self.config.config_dir, kind + "1.pem"), live_path)
|
||||
|
||||
# run update symlinks
|
||||
cert_manager.update_live_symlinks(self.config)
|
||||
|
||||
# check that symlinks go where they should
|
||||
prev_dir = os.getcwd()
|
||||
try:
|
||||
for domain in self.domains:
|
||||
for kind in ALL_FOUR:
|
||||
os.chdir(os.path.dirname(self.config_files[domain][kind]))
|
||||
assert filesystem.realpath(filesystem.readlink(self.config_files[domain][kind])) == \
|
||||
filesystem.realpath(archive_paths[domain][kind])
|
||||
finally:
|
||||
os.chdir(prev_dir)
|
||||
|
||||
|
||||
class DeleteTest(storage_test.BaseRenewableCertTest):
|
||||
"""Tests for certbot._internal.cert_manager.delete
|
||||
"""
|
||||
|
||||
@@ -594,7 +594,7 @@ class ParseTest(unittest.TestCase):
|
||||
assert_set_by_user_with_value(namespace, 'text_mode', True)
|
||||
assert_set_by_user_with_value(namespace, 'verbose_count', 1)
|
||||
assert_set_by_user_with_value(namespace, 'email', 'foo@example.com')
|
||||
|
||||
|
||||
def test_arg_with_contained_spaces(self):
|
||||
# This can happen if a user specifies an arg like "-d foo.com" enclosed
|
||||
# in double quotes, or as its own line in a docker-compose.yml file (as
|
||||
|
||||
@@ -48,7 +48,6 @@ class NamespaceConfigTest(test_util.ConfigTestCase):
|
||||
def test_dynamic_dirs(self, mock_constants):
|
||||
mock_constants.ACCOUNTS_DIR = 'acc'
|
||||
mock_constants.BACKUP_DIR = 'backups'
|
||||
mock_constants.CSR_DIR = 'csr'
|
||||
|
||||
mock_constants.IN_PROGRESS_DIR = '../p'
|
||||
mock_constants.KEY_DIR = 'keys'
|
||||
@@ -60,12 +59,6 @@ class NamespaceConfigTest(test_util.ConfigTestCase):
|
||||
os.path.normpath(os.path.join(self.config.config_dir, ref_path))
|
||||
assert os.path.normpath(self.config.backup_dir) == \
|
||||
os.path.normpath(os.path.join(self.config.work_dir, 'backups'))
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
assert os.path.normpath(self.config.csr_dir) == \
|
||||
os.path.normpath(os.path.join(self.config.config_dir, 'csr'))
|
||||
assert os.path.normpath(self.config.key_dir) == \
|
||||
os.path.normpath(os.path.join(self.config.config_dir, 'keys'))
|
||||
assert os.path.normpath(self.config.in_progress_dir) == \
|
||||
os.path.normpath(os.path.join(self.config.work_dir, '../p'))
|
||||
assert os.path.normpath(self.config.temp_checkpoint_dir) == \
|
||||
@@ -100,10 +93,6 @@ class NamespaceConfigTest(test_util.ConfigTestCase):
|
||||
os.path.join(os.getcwd(), logs_base)
|
||||
assert os.path.isabs(config.accounts_dir)
|
||||
assert os.path.isabs(config.backup_dir)
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
assert os.path.isabs(config.csr_dir)
|
||||
assert os.path.isabs(config.key_dir)
|
||||
assert os.path.isabs(config.in_progress_dir)
|
||||
assert os.path.isabs(config.temp_checkpoint_dir)
|
||||
|
||||
|
||||
@@ -1215,11 +1215,6 @@ class MainTest(test_util.ConfigTestCase):
|
||||
client.rollback.assert_called_once_with(
|
||||
mock.ANY, 123, mock.ANY, mock.ANY)
|
||||
|
||||
@mock.patch('certbot._internal.cert_manager.update_live_symlinks')
|
||||
def test_update_symlinks(self, mock_cert_manager):
|
||||
self._call_no_clientmock(['update_symlinks'])
|
||||
assert 1 == mock_cert_manager.call_count
|
||||
|
||||
@mock.patch('certbot._internal.cert_manager.certificates')
|
||||
def test_certificates(self, mock_cert_manager):
|
||||
self._call_no_clientmock(['certificates'])
|
||||
|
||||
@@ -838,21 +838,6 @@ class RenewableCertTests(BaseRenewableCertTest):
|
||||
assert stat.S_IMODE(os.lstat(temp).st_mode) == \
|
||||
stat.S_IMODE(os.lstat(temp2).st_mode)
|
||||
|
||||
def test_update_symlinks(self):
|
||||
from certbot._internal import storage
|
||||
archive_dir_path = os.path.join(self.config.config_dir, "archive", "example.org")
|
||||
for kind in ALL_FOUR:
|
||||
live_path = self.config_file[kind]
|
||||
basename = kind + "1.pem"
|
||||
archive_path = os.path.join(archive_dir_path, basename)
|
||||
open(archive_path, 'a').close()
|
||||
os.symlink(os.path.join(self.config.config_dir, basename), live_path)
|
||||
with pytest.raises(errors.CertStorageError):
|
||||
storage.RenewableCert(self.config_file.filename,
|
||||
self.config)
|
||||
storage.RenewableCert(self.config_file.filename, self.config,
|
||||
update_symlinks=True)
|
||||
|
||||
def test_truncate(self):
|
||||
# It should not do anything when there's less than 5 cert history
|
||||
for kind in ALL_FOUR:
|
||||
|
||||
@@ -8,7 +8,6 @@ from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from urllib import parse
|
||||
import warnings
|
||||
|
||||
from certbot import errors
|
||||
from certbot import util
|
||||
@@ -43,9 +42,7 @@ class NamespaceConfig:
|
||||
paths defined in :py:mod:`certbot._internal.constants`:
|
||||
|
||||
- `accounts_dir`
|
||||
- `csr_dir`
|
||||
- `in_progress_dir`
|
||||
- `key_dir`
|
||||
- `temp_checkpoint_dir`
|
||||
|
||||
And the following paths are dynamically resolved using
|
||||
@@ -285,25 +282,11 @@ class NamespaceConfig:
|
||||
"""Configuration backups directory."""
|
||||
return os.path.join(self.namespace.work_dir, constants.BACKUP_DIR)
|
||||
|
||||
@property
|
||||
def csr_dir(self) -> str:
|
||||
"""Directory where new Certificate Signing Requests (CSRs) are saved."""
|
||||
warnings.warn("NamespaceConfig.csr_dir is deprecated and will be removed in an upcoming "
|
||||
"release of Certbot", DeprecationWarning)
|
||||
return os.path.join(self.namespace.config_dir, constants.CSR_DIR)
|
||||
|
||||
@property
|
||||
def in_progress_dir(self) -> str:
|
||||
"""Directory used before a permanent checkpoint is finalized."""
|
||||
return os.path.join(self.namespace.work_dir, constants.IN_PROGRESS_DIR)
|
||||
|
||||
@property
|
||||
def key_dir(self) -> str:
|
||||
"""Keys storage."""
|
||||
warnings.warn("NamespaceConfig.key_dir is deprecated and will be removed in an upcoming "
|
||||
"release of Certbot", DeprecationWarning)
|
||||
return os.path.join(self.namespace.config_dir, constants.KEY_DIR)
|
||||
|
||||
@property
|
||||
def temp_checkpoint_dir(self) -> str:
|
||||
"""Temporary checkpoint directory."""
|
||||
|
||||
@@ -25,6 +25,10 @@ from certbot.plugins import common
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# As of writing this, the only one of our plugins that does not inherit from this class (either
|
||||
# directly or indirectly through certbot.plugins.dns_common_lexicon.LexiconDNSAuthenticator) is
|
||||
# certbot-dns-route53. If you are attempting to make changes to all of our DNS plugins, please keep
|
||||
# this difference in mind.
|
||||
class DNSAuthenticator(common.Plugin, interfaces.Authenticator, metaclass=abc.ABCMeta):
|
||||
"""Base class for DNS Authenticators"""
|
||||
|
||||
|
||||
@@ -122,7 +122,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/2.11.0 (certbot;
|
||||
"". (default: CertbotACMEClient/3.0.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,
|
||||
|
||||
@@ -17,8 +17,11 @@ its dependencies, Certbot needs to be run on a UNIX-like OS so if you're using
|
||||
Windows, you'll need to set up a (virtual) machine running an OS such as Linux
|
||||
and continue with these instructions on that UNIX-like OS.
|
||||
|
||||
If you're using macOS, it is recommended to first check out the `macOS
|
||||
suggestions`_ section before continuing with the installation instructions
|
||||
below.
|
||||
|
||||
.. _local copy:
|
||||
.. _prerequisites:
|
||||
|
||||
Running a local copy of the client
|
||||
----------------------------------
|
||||
@@ -48,9 +51,10 @@ Install and configure the OS system dependencies required to run Certbot.
|
||||
sudo dnf install python3 augeas-libs
|
||||
# For macOS installations with Homebrew already installed and configured
|
||||
# NB: If you also run `brew install python` you don't need the ~/lib
|
||||
# directory created below, however, Certbot's Apache plugin won't work
|
||||
# if you use Python installed from other sources such as pyenv or the
|
||||
# version provided by Apple.
|
||||
# directory created below, however, without this directory and symlinks
|
||||
# to augeas, Certbot's Apache plugin won't work if you use Python
|
||||
# installed from other sources such as pyenv or the version provided by
|
||||
# Apple.
|
||||
brew install augeas
|
||||
mkdir ~/lib
|
||||
ln -s $(brew --prefix)/lib/libaugeas* ~/lib
|
||||
@@ -92,17 +96,15 @@ found in the `virtualenv docs`_.
|
||||
Find issues to work on
|
||||
----------------------
|
||||
|
||||
You can find the open issues in the `github issue tracker`_. Comparatively
|
||||
easy ones are marked `good first issue`_. If you're starting work on
|
||||
something, post a comment to let others know and seek feedback on your plan
|
||||
where appropriate.
|
||||
You can find the open issues in the `github issue tracker`_. If you're starting
|
||||
work on something, post a comment to let others know and seek feedback on your
|
||||
plan where appropriate.
|
||||
|
||||
Once you've got a working branch, you can open a pull request. All changes in
|
||||
your pull request must have thorough unit test coverage, pass our
|
||||
tests, and be compliant with the :ref:`coding style <coding-style>`.
|
||||
|
||||
.. _github issue tracker: https://github.com/certbot/certbot/issues
|
||||
.. _good first issue: https://github.com/certbot/certbot/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22
|
||||
|
||||
.. _testing:
|
||||
|
||||
@@ -254,8 +256,8 @@ certificate once it is issued. Some plugins, like the built-in Apache and Nginx
|
||||
plugins, implement both interfaces and perform both tasks. Others, like the
|
||||
built-in Standalone authenticator, implement just one interface.
|
||||
|
||||
.. _interfaces.py: https://github.com/certbot/certbot/blob/master/certbot/certbot/interfaces.py
|
||||
.. _plugins/common.py: https://github.com/certbot/certbot/blob/master/certbot/certbot/plugins/common.py#L45
|
||||
.. _interfaces.py: https://github.com/certbot/certbot/blob/main/certbot/certbot/interfaces.py
|
||||
.. _plugins/common.py: https://github.com/certbot/certbot/blob/main/certbot/certbot/plugins/common.py#L45
|
||||
|
||||
|
||||
Authenticators
|
||||
@@ -375,8 +377,8 @@ Certbot plugin snaps expose their Python modules to the Certbot snap via a
|
||||
`snap content interface`_ where ``certbot-1`` is the value for the ``content``
|
||||
attribute. The Certbot snap only uses this to find the names of connected
|
||||
plugin snaps and it expects to find the Python modules to be loaded under
|
||||
``lib/python3.8/site-packages/`` in the plugin snap. This location is the
|
||||
default when using the ``core20`` `base snap`_ and the `python snapcraft
|
||||
``lib/python3.12/site-packages/`` in the plugin snap. This location is the
|
||||
default when using the ``core24`` `base snap`_ and the `python snapcraft
|
||||
plugin`_.
|
||||
|
||||
The Certbot snap also provides a separate content interface which
|
||||
@@ -385,7 +387,7 @@ identifier ``metadata-1``.
|
||||
|
||||
The script used to generate the snapcraft.yaml files for our own externally
|
||||
snapped plugins can be found at
|
||||
https://github.com/certbot/certbot/blob/master/tools/snap/generate_dnsplugins_snapcraft.sh.
|
||||
https://github.com/certbot/certbot/blob/main/tools/snap/generate_dnsplugins_snapcraft.sh.
|
||||
|
||||
For more information on building externally snapped plugins, see the section on
|
||||
:ref:`Building snaps`.
|
||||
@@ -558,7 +560,7 @@ Building the Certbot and DNS plugin snaps
|
||||
|
||||
Instructions for how to manually build and run the Certbot snap and the externally
|
||||
snapped DNS plugins that the Certbot project supplies are located in the README
|
||||
file at https://github.com/certbot/certbot/tree/master/tools/snap.
|
||||
file at https://github.com/certbot/certbot/tree/main/tools/snap.
|
||||
|
||||
Updating the documentation
|
||||
==========================
|
||||
@@ -647,3 +649,28 @@ If a dependency is already packaged in these distros and is acceptable for use i
|
||||
the oldest packaged version of that dependency should be chosen and set as the minimum
|
||||
version in ``setup.py``.
|
||||
|
||||
macOS suggestions
|
||||
=================
|
||||
|
||||
If you're developing on macOS, before :ref:`setting up your Certbot development
|
||||
environment <local copy>`, it is recommended you perform the following steps.
|
||||
None of this is required, but it is the approach used by all/most of the
|
||||
current Certbot developers on macOS as of writing this:
|
||||
|
||||
0. Install `Homebrew <https://brew.sh/>`_. It is the most popular package
|
||||
manager on macOS by a wide margin and works well enough.
|
||||
1. Install `pyenv <https://github.com/pyenv/pyenv>`_, ideally through Homebrew
|
||||
by running ``brew install pyenv``. Using Homebrew's Python for Certbot
|
||||
development is annoying because it regularly updates and every time it does
|
||||
it breaks your virtual environments. Using Python from ``pyenv`` avoids this
|
||||
problem and gives you easy access to all versions of Python.
|
||||
2. If you're using ``pyenv``, make sure you've set up your shell for it by
|
||||
following instructions like
|
||||
https://github.com/pyenv/pyenv?tab=readme-ov-file#set-up-your-shell-environment-for-pyenv.
|
||||
3. Configure ``git`` to ignore the ``.DS_Store`` files that are created by
|
||||
macOS's file manager Finder by running something like:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
mkdir -p ~/.config/git
|
||||
echo '.DS_Store' >> ~/.config/git/ignore
|
||||
|
||||
@@ -25,7 +25,7 @@ We release packages and upload them to PyPI (wheels and source tarballs).
|
||||
|
||||
The following scripts are used in the process:
|
||||
|
||||
- https://github.com/certbot/certbot/blob/master/tools/release.sh
|
||||
- https://github.com/certbot/certbot/blob/main/tools/release.sh
|
||||
|
||||
We use git tags to identify releases, using `Semantic Versioning`_. For
|
||||
example: `v0.11.1`.
|
||||
@@ -50,7 +50,7 @@ key servers.
|
||||
Notes for package maintainers
|
||||
=============================
|
||||
|
||||
0. Please use our tagged releases, not ``master``!
|
||||
0. Please use our tagged releases, not ``main``!
|
||||
|
||||
1. Do not package ``certbot-compatibility-test`` as it's only used internally.
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ Apache
|
||||
------
|
||||
|
||||
The Apache plugin currently `supports
|
||||
<https://github.com/certbot/certbot/blob/master/certbot-apache/certbot_apache/_internal/entrypoint.py>`_
|
||||
<https://github.com/certbot/certbot/blob/main/certbot-apache/certbot_apache/_internal/entrypoint.py>`_
|
||||
modern OSes based on Debian, Fedora, SUSE, Gentoo, CentOS and Darwin.
|
||||
This automates both obtaining *and* installing certificates on an Apache
|
||||
webserver. To specify this plugin on the command line, simply include
|
||||
@@ -327,6 +327,7 @@ standalone-nfq_ Y N HTTP Authentication that works with any webserver (
|
||||
dns-solidserver_ Y N DNS Authentication using SOLIDserver (EfficientIP)
|
||||
dns-stackit_ Y N DNS Authentication using STACKIT DNS
|
||||
dns-ionos_ Y N DNS Authentication using IONOS Cloud DNS
|
||||
dns-mijn-host_ Y N DNS Authentication using mijn.host DNS
|
||||
================== ==== ==== ===============================================================
|
||||
|
||||
.. _haproxy: https://github.com/greenhost/certbot-haproxy
|
||||
@@ -355,6 +356,7 @@ dns-ionos_ Y N DNS Authentication using IONOS Cloud DNS
|
||||
.. _dns-solidserver: https://gitlab.com/charlyhong/certbot-dns-solidserver
|
||||
.. _dns-stackit: https://github.com/stackitcloud/certbot-dns-stackit
|
||||
.. _dns-ionos: https://github.com/ionos-cloud/certbot-dns-ionos-cloud
|
||||
.. _dns-mijn-host: https://github.com/mijnhost/certbot-dns-mijn-host
|
||||
|
||||
If you're interested, you can also :ref:`write your own plugin <dev-plugin>`.
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ install_requires = [
|
||||
'distro>=1.0.1',
|
||||
'importlib_resources>=1.3.1; python_version < "3.9"',
|
||||
'importlib_metadata>=4.6; python_version < "3.10"',
|
||||
'josepy>=1.13.0',
|
||||
# Josepy 2+ may introduce backward incompatible changes by droping usage of
|
||||
# deprecated PyOpenSSL APIs.
|
||||
'josepy>=1.13.0, <2',
|
||||
'parsedatetime>=2.4',
|
||||
'pyrfc3339',
|
||||
'pytz>=2019.3',
|
||||
@@ -83,7 +85,6 @@ test_extras = [
|
||||
'types-pywin32',
|
||||
'types-requests',
|
||||
'types-setuptools',
|
||||
'types-six',
|
||||
'wheel',
|
||||
]
|
||||
|
||||
|
||||
@@ -66,9 +66,9 @@ parser.add_argument('--branch',
|
||||
parser.add_argument('--pull_request',
|
||||
default='~',
|
||||
help='certbot/certbot pull request to trial')
|
||||
parser.add_argument('--merge_master',
|
||||
parser.add_argument('--merge_main',
|
||||
action='store_true',
|
||||
help="if set merges PR into master branch of certbot/certbot")
|
||||
help="if set merges PR into main branch of certbot/certbot")
|
||||
parser.add_argument('--saveinstances',
|
||||
action='store_true',
|
||||
help="don't kill EC2 instances after run, useful for debugging")
|
||||
@@ -207,7 +207,7 @@ def block_until_instance_ready(booting_instance, extra_wait_time=20):
|
||||
# Fabric Routines
|
||||
#-------------------------------------------------------------------------------
|
||||
def local_git_clone(local_cxn, repo_url, log_dir):
|
||||
"""clones master of repo_url"""
|
||||
"""clones main of repo_url"""
|
||||
local_cxn.local('cd %s && if [ -d letsencrypt ]; then rm -rf letsencrypt; fi' % log_dir)
|
||||
local_cxn.local('cd %s && git clone %s letsencrypt'% (log_dir, repo_url))
|
||||
local_cxn.local('cd %s && tar czf le.tar.gz letsencrypt'% log_dir)
|
||||
@@ -219,17 +219,17 @@ def local_git_branch(local_cxn, repo_url, branch_name, log_dir):
|
||||
(log_dir, repo_url, branch_name))
|
||||
local_cxn.local('cd %s && tar czf le.tar.gz letsencrypt' % log_dir)
|
||||
|
||||
def local_git_PR(local_cxn, repo_url, PRnumstr, log_dir, merge_master=True):
|
||||
"""clones specified pull request from repo_url and optionally merges into master"""
|
||||
def local_git_PR(local_cxn, repo_url, PRnumstr, log_dir, merge_main=True):
|
||||
"""clones specified pull request from repo_url and optionally merges into main"""
|
||||
local_cxn.local('cd %s && if [ -d letsencrypt ]; then rm -rf letsencrypt; fi' % log_dir)
|
||||
local_cxn.local('cd %s && git clone %s letsencrypt' % (log_dir, repo_url))
|
||||
local_cxn.local('cd %s && cd letsencrypt && '
|
||||
'git fetch origin pull/%s/head:lePRtest' % (log_dir, PRnumstr))
|
||||
local_cxn.local('cd %s && cd letsencrypt && git checkout lePRtest' % log_dir)
|
||||
if merge_master:
|
||||
if merge_main:
|
||||
local_cxn.local('cd %s && cd letsencrypt && git remote update origin' % log_dir)
|
||||
local_cxn.local('cd %s && cd letsencrypt && '
|
||||
'git merge origin/master -m "testmerge"' % log_dir)
|
||||
'git merge origin/main -m "testmerge"' % log_dir)
|
||||
local_cxn.local('cd %s && tar czf le.tar.gz letsencrypt' % log_dir)
|
||||
|
||||
def local_repo_to_remote(cxn, log_dir):
|
||||
@@ -286,15 +286,15 @@ def create_client_instance(ec2_client, target, security_group_id, subnet_id, sel
|
||||
# 32 bit systems
|
||||
machine_type = 'c1.medium'
|
||||
name = 'le-%s'%target['name']
|
||||
print(name, end=" ")
|
||||
return make_instance(ec2_client,
|
||||
name,
|
||||
target['ami'],
|
||||
KEYNAME,
|
||||
machine_type=machine_type,
|
||||
security_group_id=security_group_id,
|
||||
subnet_id=subnet_id,
|
||||
self_destruct=self_destruct)
|
||||
try:
|
||||
instance = make_instance(ec2_client, name, target['ami'], KEYNAME,
|
||||
machine_type=machine_type, security_group_id=security_group_id,
|
||||
subnet_id=subnet_id, self_destruct=self_destruct)
|
||||
except Exception:
|
||||
print(f'FAIL: Unable to create instance {name}')
|
||||
raise
|
||||
print(f'Created instance {name}')
|
||||
return instance
|
||||
|
||||
|
||||
def test_client_process(fab_config, inqueue, outqueue, log_dir):
|
||||
@@ -382,9 +382,9 @@ def main():
|
||||
print("Making local git repo")
|
||||
if cl_args.pull_request != '~':
|
||||
print('Testing PR %s ' % cl_args.pull_request,
|
||||
"MERGING into master" if cl_args.merge_master else "")
|
||||
"MERGING into main" if cl_args.merge_main else "")
|
||||
local_git_PR(local_cxn, cl_args.repo, cl_args.pull_request, log_dir,
|
||||
cl_args.merge_master)
|
||||
cl_args.merge_main)
|
||||
elif cl_args.branch != '~':
|
||||
print('Testing branch %s of %s' % (cl_args.branch, cl_args.repo))
|
||||
local_git_branch(local_cxn, cl_args.repo, cl_args.branch, log_dir)
|
||||
@@ -435,7 +435,6 @@ def main():
|
||||
|
||||
instances = []
|
||||
try:
|
||||
print("Creating instances: ", end="")
|
||||
# If we want to preserve instances, do not have them self-destruct.
|
||||
self_destruct = not cl_args.saveinstances
|
||||
for target in targetlist:
|
||||
@@ -444,7 +443,6 @@ def main():
|
||||
security_group_id, subnet_id,
|
||||
self_destruct)
|
||||
)
|
||||
print()
|
||||
|
||||
# Install and launch client scripts in parallel
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -33,7 +33,7 @@ targets:
|
||||
#-----------------------------------------------------------------------------
|
||||
# CentOS
|
||||
# These AMI were found on https://centos.org/download/aws-images/.
|
||||
- ami: ami-08f2fe20b72b2ffa7
|
||||
- ami: ami-00d53d23711185071
|
||||
name: centos9stream
|
||||
type: centos
|
||||
virt: hvm
|
||||
|
||||
12
pytest.ini
12
pytest.ini
@@ -19,17 +19,19 @@
|
||||
# unit tests. This warning should be ignored until our (transitive)
|
||||
# dependency on requests-toolbelt is removed or our pinned version can be
|
||||
# updated.
|
||||
# 4) Ignore our own PendingDeprecationWarning about update_symlinks soon to be dropped.
|
||||
# See https://github.com/certbot/certbot/issues/6284.
|
||||
# 5) Ignore DeprecationWarning for datetime.utcfromtimestamp() triggered
|
||||
# 4) Ignore DeprecationWarning for datetime.utcfromtimestamp() triggered
|
||||
# from dateutil. See https://github.com/dateutil/dateutil/issues/1314.
|
||||
# 6) Ignoring this allows us to continue to update pyOpenSSL (one of our crypto
|
||||
# 5) Ignoring this allows us to continue to update pyOpenSSL (one of our crypto
|
||||
# dependencies) until https://github.com/certbot/certbot/issues/9828 is resolved.
|
||||
# 6) Similarly to 6), CSR support is deprecated in pyOpenSSL since 24.2, we silence
|
||||
# the warning until https://github.com/certbot/certbot/issues/9992 is resolved.
|
||||
# 7) Ignore our own PendingDeprecationWarning about Python 3.8 soon to be dropped.
|
||||
filterwarnings =
|
||||
error
|
||||
ignore:decodestring\(\) is a deprecated alias:DeprecationWarning:dns
|
||||
ignore:.*rsyncdir:DeprecationWarning
|
||||
ignore:'urllib3.contrib.pyopenssl:DeprecationWarning:requests_toolbelt
|
||||
ignore:update_symlinks is deprecated:PendingDeprecationWarning
|
||||
ignore:.*datetime.utcfromtimestamp\(\) is deprecated:DeprecationWarning:dateutil
|
||||
ignore:X509Extension support in pyOpenSSL is deprecated:DeprecationWarning
|
||||
ignore:CSR support in pyOpenSSL is deprecated:DeprecationWarning
|
||||
ignore:Python 3.8 support will be dropped:PendingDeprecationWarning
|
||||
|
||||
@@ -14,13 +14,16 @@ description: |
|
||||
- Keep track of when your certificate is going to expire, and renew it
|
||||
- Help you revoke the certificate if that ever becomes necessary.
|
||||
confinement: classic
|
||||
base: core20
|
||||
base: core24
|
||||
grade: stable
|
||||
adopt-info: certbot
|
||||
|
||||
environment:
|
||||
PYTHONPATH: "$SNAP/lib/python3.12/site-packages:${PYTHONPATH}"
|
||||
|
||||
apps:
|
||||
certbot:
|
||||
command: bin/python3 -s $SNAP/bin/certbot
|
||||
command: bin/python3-dbg -s $SNAP/bin/certbot
|
||||
environment:
|
||||
PATH: "$SNAP/bin:$SNAP/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
|
||||
AUGEAS_LENS_LIB: "$SNAP/usr/share/augeas/lenses/dist"
|
||||
@@ -47,7 +50,8 @@ parts:
|
||||
- ./certbot-apache
|
||||
- ./certbot-nginx
|
||||
stage:
|
||||
- -usr/lib/python3.8/sitecustomize.py # maybe unnecessary
|
||||
- -usr/lib/python3.12/sitecustomize.py # maybe unnecessary
|
||||
- -pyvenv.cfg
|
||||
# Old versions of this file used to unstage
|
||||
# lib/python3.8/site-packages/augeas.py to avoid conflicts between
|
||||
# python-augeas 0.5.0 which was pinned in snap-constraints.txt and
|
||||
@@ -57,19 +61,20 @@ parts:
|
||||
# effect so we now stage the file to keep the auto-generated cffi file.
|
||||
stage-packages:
|
||||
- libaugeas0
|
||||
- libpython3.8-dev
|
||||
- libpython3.12-dev
|
||||
# added to stage python:
|
||||
- libpython3-stdlib
|
||||
- libpython3.8-stdlib
|
||||
- libpython3.8-minimal
|
||||
- libpython3.12-stdlib
|
||||
- libpython3.12-minimal
|
||||
- python3-pip
|
||||
- python3-wheel
|
||||
- python3-venv
|
||||
- python3-minimal
|
||||
- python3-distutils
|
||||
- python3-pkg-resources
|
||||
- python3.8-minimal
|
||||
# To build cryptography and cffi if needed
|
||||
- python3.12-minimal
|
||||
- libpython3-all-dbg
|
||||
- python3-dbg
|
||||
- python3.12-dbg
|
||||
build-packages:
|
||||
- gcc
|
||||
- git
|
||||
@@ -77,7 +82,9 @@ parts:
|
||||
- build-essential
|
||||
- libssl-dev
|
||||
- libffi-dev
|
||||
- python3-dev
|
||||
- libpython3-all-dbg
|
||||
- python3-dbg
|
||||
- python3-venv
|
||||
- cargo
|
||||
- pkg-config
|
||||
build-environment:
|
||||
@@ -85,28 +92,31 @@ parts:
|
||||
# stability of fetching the rust crates needed to build the cryptography
|
||||
# library.
|
||||
- CARGO_NET_GIT_FETCH_WITH_CLI: "true"
|
||||
- SNAPCRAFT_PYTHON_VENV_ARGS: --upgrade
|
||||
- PARTS_PYTHON_VENV_ARGS: --upgrade
|
||||
# Constraints are passed through the environment variable PIP_CONSTRAINTS instead of using the
|
||||
# parts.[part_name].constraints option available in snapcraft.yaml when the Python plugin is
|
||||
# used. This is done to let these constraints be applied not only on the certbot package
|
||||
# build, but also on any isolated build that pip could trigger when building wheels for
|
||||
# dependencies. See https://github.com/certbot/certbot/pull/8443 for more info.
|
||||
- PIP_CONSTRAINT: $SNAPCRAFT_PART_SRC/snap-constraints.txt
|
||||
- PIP_CONSTRAINT: $CRAFT_PART_SRC/snap-constraints.txt
|
||||
- PARTS_PYTHON_INTERPRETER: "python3-dbg"
|
||||
override-build: |
|
||||
python3 -m venv "${SNAPCRAFT_PART_INSTALL}"
|
||||
"${SNAPCRAFT_PART_INSTALL}/bin/python3" "${SNAPCRAFT_PART_SRC}/tools/pipstrap.py"
|
||||
snapcraftctl build
|
||||
python3-dbg -m venv "${CRAFT_PART_INSTALL}"
|
||||
"${CRAFT_PART_INSTALL}/bin/python3-dbg" "${CRAFT_PART_SRC}/tools/pipstrap.py"
|
||||
craftctl default
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
grep -v python-augeas "${SNAPCRAFT_PART_SRC}/tools/requirements.txt" >> "${SNAPCRAFT_PART_SRC}/snap-constraints.txt"
|
||||
snapcraftctl set-version `grep -oP "__version__ = '\K.*(?=')" "${SNAPCRAFT_PART_SRC}/certbot/certbot/__init__.py"`
|
||||
craftctl default
|
||||
grep -v python-augeas "${CRAFT_PART_SRC}/tools/requirements.txt" >> "${CRAFT_PART_SRC}/snap-constraints.txt"
|
||||
craftctl set version=$(grep -oP "__version__ = '\K.*(?=')" "${CRAFT_PART_SRC}/certbot/certbot/__init__.py")
|
||||
build-attributes:
|
||||
- enable-patchelf
|
||||
shared-metadata:
|
||||
plugin: dump
|
||||
source: .
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
craftctl default
|
||||
mkdir -p certbot-metadata
|
||||
grep -oP "__version__ = '\K.*(?=')" $SNAPCRAFT_PART_SRC/certbot/certbot/__init__.py > certbot-metadata/certbot-version.txt
|
||||
grep -oP "__version__ = '\K.*(?=')" $CRAFT_PART_SRC/certbot/certbot/__init__.py > certbot-metadata/certbot-version.txt
|
||||
stage: [certbot-metadata/certbot-version.txt]
|
||||
|
||||
plugs:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## nextversion - master
|
||||
## nextversion - main
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ if [ "$RELEASE_GPG_KEY" = "" ]; then
|
||||
F2871B4152AE13C49519111F447BF683AA3B26C3
|
||||
"
|
||||
for key in $TRUSTED_KEYS; do
|
||||
if gpg2 --with-colons --card-status | grep -q "$key"; then
|
||||
if gpg --with-colons --card-status | grep -q "$key"; then
|
||||
RELEASE_GPG_KEY="$key"
|
||||
break
|
||||
fi
|
||||
@@ -97,7 +97,7 @@ fi
|
||||
git checkout "$RELEASE_BRANCH"
|
||||
|
||||
# Update changelog
|
||||
sed -i "s/master/$(date +'%Y-%m-%d')/" certbot/CHANGELOG.md
|
||||
sed -i "0,/main/ s/main/$(date +'%Y-%m-%d')/" certbot/CHANGELOG.md
|
||||
git add certbot/CHANGELOG.md
|
||||
git commit -m "Update changelog for $version release"
|
||||
|
||||
@@ -157,7 +157,7 @@ done
|
||||
cd "$built_package_dir"
|
||||
echo "Generating checksum file and signing it"
|
||||
sha256sum *.tar.gz > SHA256SUMS
|
||||
gpg2 -u "$RELEASE_GPG_KEY" --detach-sign --armor --sign --digest-algo sha256 SHA256SUMS
|
||||
gpg -u "$RELEASE_GPG_KEY" --detach-sign --armor --sign --digest-algo sha256 SHA256SUMS
|
||||
git add *.tar.gz SHA256SUMS*
|
||||
|
||||
echo "Installing packages to generate documentation"
|
||||
@@ -196,8 +196,8 @@ deactivate
|
||||
git add certbot/docs/cli-help.txt
|
||||
while ! git commit --gpg-sign="$RELEASE_GPG_KEY" -m "Release $version"; do
|
||||
echo "Unable to sign the release commit using git."
|
||||
echo "You may have to configure git to use gpg2 by running:"
|
||||
echo 'git config --global gpg.program $(command -v gpg2)'
|
||||
echo "You may have to configure git to use gpg by running:"
|
||||
echo 'git config --global gpg.program $(command -v gpg)'
|
||||
read -p "Press enter to try signing again."
|
||||
done
|
||||
git tag --local-user "$RELEASE_GPG_KEY" --sign --message "Release $version" "$tag"
|
||||
@@ -205,7 +205,7 @@ git tag --local-user "$RELEASE_GPG_KEY" --sign --message "Release $version" "$ta
|
||||
git rm --cached -r "$built_package_dir"
|
||||
git commit -m "Remove built packages from git"
|
||||
|
||||
# Add master section to CHANGELOG.md
|
||||
# Add main section to CHANGELOG.md
|
||||
header=$(head -n 4 certbot/CHANGELOG.md)
|
||||
body=$(sed s/nextversion/$nextversion/ tools/_changelog_top.txt)
|
||||
footer=$(tail -n +5 certbot/CHANGELOG.md)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#base image
|
||||
FROM python:3.12-alpine3.18 as certbot
|
||||
FROM python:3.12-alpine3.18 AS certbot
|
||||
|
||||
ENTRYPOINT [ "certbot" ]
|
||||
EXPOSE 80 443
|
||||
@@ -25,6 +25,12 @@ RUN apk add --no-cache --virtual .certbot-deps \
|
||||
# cryptography library
|
||||
ARG CARGO_NET_GIT_FETCH_WITH_CLI=true
|
||||
# Install certbot from sources
|
||||
#
|
||||
# For some reason, setting the CARGO_LOG and CARGO_TERM_VERBOSE environment
|
||||
# variables and -v/--verbose flags on pip seems to help cryptography builds not
|
||||
# hang when building Docker images for other architectures using QEMU. See
|
||||
# https://github.com/certbot/certbot/issues/10020. This may hopefully also help
|
||||
# us to get more information about the problem to aid further debugging.
|
||||
RUN apk add --no-cache --virtual .build-deps \
|
||||
gcc \
|
||||
linux-headers \
|
||||
@@ -35,7 +41,8 @@ RUN apk add --no-cache --virtual .build-deps \
|
||||
cargo \
|
||||
git \
|
||||
pkgconfig \
|
||||
&& python tools/pip_install.py --no-cache-dir \
|
||||
&& CARGO_LOG=trace CARGO_TERM_VERBOSE=true python tools/pip_install.py \
|
||||
--no-cache-dir -vvv \
|
||||
--editable src/acme \
|
||||
--editable src/certbot \
|
||||
&& apk del .build-deps \
|
||||
@@ -44,6 +51,6 @@ RUN apk add --no-cache --virtual .build-deps \
|
||||
#static definition for making a plugin, but beware that
|
||||
#using this layer definition will cause collisions if you make
|
||||
#extensive use of the cache.
|
||||
FROM certbot as certbot-plugin
|
||||
FROM certbot AS certbot-plugin
|
||||
COPY --from=plugin-src . /opt/certbot/src/plugin
|
||||
RUN python tools/pip_install.py --no-cache-dir --editable /opt/certbot/src/plugin
|
||||
|
||||
@@ -70,7 +70,7 @@ ParseArgs() {
|
||||
local IFS=","
|
||||
# Handle the special value "all"
|
||||
if [[ "${ARCH_LIST}" == "all" ]]; then
|
||||
# Replace with comma separated
|
||||
# Replace with comma separated
|
||||
ARCH_LIST="${ALL_TARGET_ARCH[*]}"
|
||||
fi
|
||||
|
||||
@@ -88,7 +88,7 @@ ParseArgs() {
|
||||
}
|
||||
|
||||
|
||||
# Function for use with trap in the primary scripts to remove the
|
||||
# Function for use with trap in the primary scripts to remove the
|
||||
# docker builder and restore the original directory
|
||||
Cleanup() {
|
||||
docker buildx rm certbot_builder || true
|
||||
@@ -106,5 +106,11 @@ CreateBuilder() {
|
||||
# just incase the env is not perfectly clean, remove any old instance of the builder
|
||||
docker buildx rm certbot_builder || true
|
||||
# create the builder instance
|
||||
docker buildx create --name certbot_builder --driver docker-container --driver-opt=network=host --bootstrap
|
||||
}
|
||||
#
|
||||
# BUILDKIT_STEP_LOG_MAX_* environment variables are set to prevent docker
|
||||
# from truncating build logs that can be useful during debugging. See
|
||||
# https://github.com/docker/buildx/issues/484#issuecomment-749352728
|
||||
docker buildx create --name certbot_builder --driver docker-container \
|
||||
--driver-opt=network=host --driver-opt env.BUILDKIT_STEP_LOG_MAX_SIZE=-1 \
|
||||
--driver-opt env.BUILDKIT_STEP_LOG_MAX_SPEED=-1 --bootstrap
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ def get_snap_revisions(snap, channel, version):
|
||||
print('Getting revision numbers for', snap, version)
|
||||
cmd = ['snapcraft', 'status', snap]
|
||||
process = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True)
|
||||
pattern = f'^\s+{channel}\s+{version}\s+(\d+)\s*'
|
||||
pattern = f'^\\s+{channel}\\s+{version}\\s+(\\d+)\\s*'
|
||||
revisions = re.findall(pattern, process.stdout, re.MULTILINE)
|
||||
assert len(revisions) == SNAP_ARCH_COUNT, f'Unexpected number of snaps found for {channel} {snap} {version} (expected {SNAP_ARCH_COUNT}, found {len(revisions)})'
|
||||
return revisions
|
||||
|
||||
@@ -2,98 +2,98 @@
|
||||
# that script.
|
||||
apacheconfig==0.3.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
asn1crypto==0.24.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
astroid==3.0.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
beautifulsoup4==4.12.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
astroid==3.2.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
beautifulsoup4==4.12.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
boto3==1.15.15 ; python_version >= "3.8" and python_version < "3.9"
|
||||
botocore==1.18.15 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cachetools==5.3.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
certifi==2023.11.17 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cachetools==5.5.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
certifi==2024.7.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cffi==1.12.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
chardet==3.0.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cloudflare==1.5.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
colorama==0.4.6 ; python_version >= "3.8" and python_version < "3.9" and sys_platform == "win32"
|
||||
configargparse==1.5.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
configobj==5.0.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
coverage==7.3.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
coverage==7.6.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cryptography==3.2.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cython==0.29.36 ; python_version >= "3.8" and python_version < "3.9"
|
||||
dill==0.3.7 ; python_version >= "3.8" and python_version < "3.9"
|
||||
distlib==0.3.7 ; python_version >= "3.8" and python_version < "3.9"
|
||||
cython==0.29.37 ; python_version >= "3.8" and python_version < "3.9"
|
||||
dill==0.3.8 ; python_version >= "3.8" and python_version < "3.9"
|
||||
distlib==0.3.8 ; python_version >= "3.8" and python_version < "3.9"
|
||||
distro==1.0.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
dns-lexicon==3.15.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
dnspython==1.15.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
exceptiongroup==1.2.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
execnet==2.0.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
filelock==3.13.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
exceptiongroup==1.2.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
execnet==2.1.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
filelock==3.15.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
funcsigs==0.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
future==0.18.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
future==1.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
google-api-python-client==1.6.5 ; python_version >= "3.8" and python_version < "3.9"
|
||||
google-auth==2.16.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
httplib2==0.9.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
idna==2.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
importlib-metadata==4.6.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
importlib-resources==6.1.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
importlib-resources==6.4.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
iniconfig==2.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
ipaddress==1.0.16 ; python_version >= "3.8" and python_version < "3.9"
|
||||
isort==5.12.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
isort==5.13.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
jmespath==0.10.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
josepy==1.14.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
logger==1.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
mccabe==0.7.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
mypy-extensions==1.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
mypy==1.7.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
mypy==1.11.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
ndg-httpsclient==0.3.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
oauth2client==4.1.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
packaging==23.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
packaging==24.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
parsedatetime==2.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pbr==1.8.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pip==23.3.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
platformdirs==4.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pluggy==1.3.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pip==24.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
platformdirs==4.2.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pluggy==1.5.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
ply==3.4 ; python_version >= "3.8" and python_version < "3.9"
|
||||
py==1.11.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyasn1-modules==0.3.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyasn1-modules==0.4.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyasn1==0.4.8 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pycparser==2.14 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pylint==3.0.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pylint==3.2.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyopenssl==17.5.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyotp==2.9.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyparsing==2.2.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyrfc3339==1.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest-cov==4.1.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest-xdist==3.5.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest==7.4.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest-cov==5.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest-xdist==3.6.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytest==8.3.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
python-augeas==0.5.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
python-dateutil==2.8.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
python-dateutil==2.9.0.post0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
python-digitalocean==1.11 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pytz==2019.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pywin32==306 ; python_version >= "3.8" and python_version < "3.9" and sys_platform == "win32"
|
||||
pyyaml==6.0.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
requests-file==1.5.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
pyyaml==6.0.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
requests-file==2.1.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
requests==2.20.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
rsa==4.9 ; python_version >= "3.8" and python_version < "3.9"
|
||||
s3transfer==0.3.7 ; python_version >= "3.8" and python_version < "3.9"
|
||||
setuptools==41.6.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
six==1.11.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
soupsieve==2.5 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tldextract==5.1.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
soupsieve==2.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tldextract==5.1.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tomli==2.0.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tomlkit==0.12.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tomlkit==0.13.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
tox==1.9.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-cryptography==3.3.23.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-httplib2==0.22.0.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-httplib2==0.22.0.20240310 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pyopenssl==23.0.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pyrfc3339==1.1.1.5 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-python-dateutil==2.8.19.14 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pytz==2023.3.1.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pywin32==306.0.0.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-python-dateutil==2.9.0.20240821 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pytz==2024.1.0.20240417 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-pywin32==306.0.0.20240822 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-requests==2.31.0.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-setuptools==69.0.0.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-six==1.16.21.9 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-setuptools==73.0.0.20240822 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-six==1.16.21.20240513 ; python_version >= "3.8" and python_version < "3.9"
|
||||
types-urllib3==1.26.25.14 ; python_version >= "3.8" and python_version < "3.9"
|
||||
typing-extensions==4.8.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
typing-extensions==4.12.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
uritemplate==3.0.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
urllib3==1.24.2 ; python_version >= "3.8" and python_version < "3.9"
|
||||
virtualenv==20.25.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
virtualenv==20.26.3 ; python_version >= "3.8" and python_version < "3.9"
|
||||
wheel==0.33.6 ; python_version >= "3.8" and python_version < "3.9"
|
||||
zipp==3.17.0 ; python_version >= "3.8" and python_version < "3.9"
|
||||
zipp==3.20.1 ; python_version >= "3.8" and python_version < "3.9"
|
||||
|
||||
@@ -19,7 +19,7 @@ CheckVersion() {
|
||||
CheckVersion "$1"
|
||||
CheckVersion "$2"
|
||||
|
||||
if [ "$RELEASE_GPG_KEY" = "" ] && ! gpg2 --card-status >/dev/null 2>&1; then
|
||||
if [ "$RELEASE_GPG_KEY" = "" ] && ! gpg --card-status >/dev/null 2>&1; then
|
||||
echo OpenPGP card not found!
|
||||
echo Please insert your PGP card and run this script again.
|
||||
exit 1
|
||||
|
||||
@@ -10,62 +10,62 @@ apacheconfig==0.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
appnope==0.1.4 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "darwin"
|
||||
astroid==3.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
asttokens==2.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
attrs==23.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
azure-core==1.30.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
attrs==24.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
azure-core==1.32.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
azure-devops==7.1.0b4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
babel==2.15.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
babel==2.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
backcall==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
bcrypt==4.1.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
bcrypt==4.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
beautifulsoup4==4.12.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
boto3==1.34.116 ; python_version >= "3.8" and python_version < "4.0"
|
||||
botocore==1.34.116 ; python_version >= "3.8" and python_version < "4.0"
|
||||
build==1.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
boto3==1.35.53 ; python_version >= "3.8" and python_version < "4.0"
|
||||
botocore==1.35.53 ; python_version >= "3.8" and python_version < "4.0"
|
||||
build==1.2.2.post1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cachecontrol==0.14.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cachetools==5.3.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
certifi==2024.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cffi==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cachetools==5.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
certifi==2024.8.30 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cffi==1.17.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
chardet==5.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
charset-normalizer==3.3.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
charset-normalizer==3.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cleo==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cloudflare==2.19.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
colorama==0.4.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||
configargparse==1.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
configobj==5.0.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||
coverage==7.5.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
configobj==5.0.9 ; python_version >= "3.8" and python_version < "4.0"
|
||||
coverage==7.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
crashtest==0.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cryptography==42.0.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cryptography==43.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
cython==0.29.37 ; python_version >= "3.8" and python_version < "4.0"
|
||||
decorator==5.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
deprecated==1.2.14 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dill==0.3.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||
distlib==0.3.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dill==0.3.9 ; python_version >= "3.8" and python_version < "4.0"
|
||||
distlib==0.3.9 ; python_version >= "3.8" and python_version < "4.0"
|
||||
distro==1.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dns-lexicon==3.17.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dns-lexicon==3.18.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dnspython==2.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
docutils==0.20.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
dulwich==0.21.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
exceptiongroup==1.2.1 ; python_version >= "3.8" and python_version < "3.11"
|
||||
exceptiongroup==1.2.2 ; python_version >= "3.8" and python_version < "3.11"
|
||||
execnet==2.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
executing==2.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
executing==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
fabric==3.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
fastjsonschema==2.19.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
filelock==3.14.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-api-core==2.19.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-api-python-client==2.131.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
fastjsonschema==2.20.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
filelock==3.16.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-api-core==2.22.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-api-python-client==2.151.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-auth-httplib2==0.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-auth==2.29.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
googleapis-common-protos==1.63.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
google-auth==2.35.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
googleapis-common-protos==1.65.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
httplib2==0.22.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
idna==3.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
idna==3.10 ; python_version >= "3.8" and python_version < "4.0"
|
||||
imagesize==1.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
importlib-metadata==7.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
importlib-resources==6.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
importlib-metadata==8.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
importlib-resources==6.4.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
iniconfig==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
installer==0.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
invoke==2.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
ipdb==0.13.13 ; python_version >= "3.8" and python_version < "4.0"
|
||||
ipython==8.12.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
isodate==0.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
isodate==0.7.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
isort==5.13.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jaraco-classes==3.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jedi==0.19.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
@@ -74,63 +74,63 @@ jinja2==3.1.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jmespath==1.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
josepy==1.14.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jsonlines==4.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jsonpickle==3.0.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
jsonpickle==3.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
keyring==24.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
markdown-it-py==3.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
markupsafe==2.1.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
matplotlib-inline==0.1.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
mccabe==0.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
mdurl==0.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
more-itertools==10.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
msgpack==1.0.8 ; python_version >= "3.8" and python_version < "4.0"
|
||||
more-itertools==10.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
msgpack==1.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
msrest==0.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
mypy-extensions==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
mypy==1.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
nh3==0.2.17 ; python_version >= "3.8" and python_version < "4.0"
|
||||
nh3==0.2.18 ; python_version >= "3.8" and python_version < "4.0"
|
||||
oauthlib==3.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
packaging==24.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
paramiko==3.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
packaging==24.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
paramiko==3.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
parsedatetime==2.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||
parso==0.8.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pexpect==4.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pickleshare==0.7.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pip==24.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pip==24.3.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pkginfo==1.10.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
platformdirs==4.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
platformdirs==4.3.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pluggy==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
ply==3.11 ; python_version >= "3.8" and python_version < "4.0"
|
||||
poetry-core==1.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
poetry-core==1.9.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
poetry-plugin-export==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
poetry==1.8.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
prompt-toolkit==3.0.45 ; python_version >= "3.8" and python_version < "4.0"
|
||||
proto-plus==1.23.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
protobuf==4.25.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
poetry==1.8.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
prompt-toolkit==3.0.48 ; python_version >= "3.8" and python_version < "4.0"
|
||||
proto-plus==1.25.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
protobuf==5.28.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
ptyprocess==0.7.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pure-eval==0.2.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyasn1-modules==0.4.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyasn1==0.6.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pure-eval==0.2.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyasn1-modules==0.4.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyasn1==0.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pycparser==2.22 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pygments==2.18.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pylint==3.0.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pynacl==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pynsist==2.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyopenssl==24.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyopenssl==24.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyotp==2.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyparsing==3.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyproject-api==1.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyproject-hooks==1.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyparsing==3.1.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyproject-api==1.8.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyproject-hooks==1.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pyrfc3339==1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytest-cov==5.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytest-xdist==3.6.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytest==8.2.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytest==8.3.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
python-augeas==1.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
python-dateutil==2.9.0.post0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
python-digitalocean==1.17.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytz==2024.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pywin32-ctypes==0.2.2 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32"
|
||||
pywin32==306 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32"
|
||||
pyyaml==6.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rapidfuzz==3.9.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pytz==2024.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
pywin32-ctypes==0.2.3 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32"
|
||||
pywin32==308 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "win32"
|
||||
pyyaml==6.0.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rapidfuzz==3.9.7 ; python_version >= "3.8" and python_version < "4.0"
|
||||
readme-renderer==43.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
requests-download==0.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
requests-file==2.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
@@ -138,18 +138,18 @@ requests-oauthlib==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
requests-toolbelt==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
requests==2.32.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rfc3986==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rich==13.7.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rich==13.9.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
rsa==4.9 ; python_version >= "3.8" and python_version < "4"
|
||||
s3transfer==0.10.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
s3transfer==0.10.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
secretstorage==3.3.3 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "linux"
|
||||
semantic-version==2.10.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
setuptools-rust==1.9.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
setuptools==70.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
setuptools-rust==1.10.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
setuptools==75.3.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
shellingham==1.5.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
six==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
snowballstemmer==2.2.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
soupsieve==2.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinx-rtd-theme==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
soupsieve==2.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinx-rtd-theme==3.0.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinx==7.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinxcontrib-applehelp==1.0.4 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinxcontrib-devhelp==1.0.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
@@ -160,30 +160,29 @@ sphinxcontrib-qthelp==1.0.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
sphinxcontrib-serializinghtml==1.1.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
stack-data==0.6.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
tldextract==5.1.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
tomli==2.0.1 ; python_version >= "3.8" and python_full_version <= "3.11.0a6"
|
||||
tomlkit==0.12.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
tox==4.15.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
tomli==2.0.2 ; python_version >= "3.8" and python_full_version <= "3.11.0a6"
|
||||
tomlkit==0.13.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
tox==4.23.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
traitlets==5.14.3 ; python_version >= "3.8" and python_version < "4.0"
|
||||
trove-classifiers==2024.5.22 ; python_version >= "3.8" and python_version < "4.0"
|
||||
twine==5.1.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
trove-classifiers==2024.10.21.16 ; python_version >= "3.8" and python_version < "4.0"
|
||||
twine==5.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-cffi==1.16.0.20240331 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-httplib2==0.22.0.20240310 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pyopenssl==24.1.0.20240425 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pyopenssl==24.1.0.20240722 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pyrfc3339==1.1.1.5 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-python-dateutil==2.9.0.20240316 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pytz==2024.1.0.20240417 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pywin32==306.0.0.20240408 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-python-dateutil==2.9.0.20241003 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pytz==2024.2.0.20241003 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-pywin32==308.0.0.20241029 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-requests==2.31.0.6 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-setuptools==70.0.0.20240524 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-six==1.16.21.20240513 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-setuptools==75.2.0.20241025 ; python_version >= "3.8" and python_version < "4.0"
|
||||
types-urllib3==1.26.25.14 ; python_version >= "3.8" and python_version < "4.0"
|
||||
typing-extensions==4.12.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
typing-extensions==4.12.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
uritemplate==4.1.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
urllib3==1.26.18 ; python_version >= "3.8" and python_version < "4.0"
|
||||
virtualenv==20.26.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
urllib3==1.26.20 ; python_version >= "3.8" and python_version < "4.0"
|
||||
virtualenv==20.27.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
wcwidth==0.2.13 ; python_version >= "3.8" and python_version < "4.0"
|
||||
wheel==0.43.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
wheel==0.44.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
wrapt==1.16.0 ; python_version >= "3.8" and python_version < "4.0"
|
||||
xattr==1.1.0 ; python_version >= "3.8" and python_version < "4.0" and sys_platform == "darwin"
|
||||
yarg==0.1.9 ; python_version >= "3.8" and python_version < "4.0"
|
||||
zipp==3.19.1 ; python_version >= "3.8" and python_version < "4.0"
|
||||
yarg==0.1.10 ; python_version >= "3.8" and python_version < "4.0"
|
||||
zipp==3.20.2 ; python_version >= "3.8" and python_version < "4.0"
|
||||
|
||||
@@ -12,7 +12,7 @@ These steps need to be done once to set up your VM and do not need to be run aga
|
||||
1. Start with a Focal VM. You need a full virtual machine using something like DigitalOcean, EC2, or VirtualBox. Docker won't work. Another version of Ubuntu can probably be used, but Focal was used when writing these instructions.
|
||||
2. Set up a user other than root with sudo privileges for use with snapcraft and run all of the following commands with it. A command to do this for a user named certbot looks like `adduser certbot && usermod -aG sudo certbot && su - certbot`.
|
||||
3. Install git and python with `sudo apt update && sudo apt install -y git python`.
|
||||
4. Set up lxd for use with snapcraft by running `sudo snap install lxd && sudo /snap/bin/lxd.migrate -yes; sudo /snap/bin/lxd waitready && sudo /snap/bin/lxd init --auto` (errors here are ok; it may already
|
||||
4. Set up lxd for use with snapcraft by running `sudo snap install lxd; sudo /snap/bin/lxd waitready && sudo /snap/bin/lxd init --auto` (errors here are ok; it may already
|
||||
have been installed on your system).
|
||||
5. Add your current user to the lxd group and update your shell to have the new assignment by running `sudo usermod -a -G lxd ${USER} && newgrp lxd`.
|
||||
6. Install snapcraft with `sudo snap install --classic snapcraft`.
|
||||
|
||||
@@ -49,26 +49,32 @@ def _snap_log_name(target: str, arch: str):
|
||||
def _execute_build(
|
||||
target: str, archs: Set[str], status: Dict[str, Dict[str, str]],
|
||||
workspace: str, output_lock: Lock) -> Tuple[int, List[str]]:
|
||||
|
||||
# snapcraft remote-build accepts a --build-id flag with snapcraft version
|
||||
# 5.0+. We make use of this feature to set a unique build ID so a fresh
|
||||
# build is started for each run instead of potentially reusing an old
|
||||
# build. See https://github.com/certbot/certbot/pull/8719 and
|
||||
# https://github.com/snapcore/snapcraft/pull/3554 for more info.
|
||||
# The implementation of remote-build recovery has changed over time.
|
||||
# Currently, you cannot set a build-id, and the build-id is instead derived
|
||||
# from a hash of the contents of the files in the directory:
|
||||
# https://github.com/canonical/craft-application/blob/5b09ab3d9152a2b61ffcdf57691289023ed6ba26/craft_application/remote/utils.py#L64
|
||||
#
|
||||
# This random string was chosen because snapcraft uses a MD5 hash
|
||||
# represented as a 32 character hex string by default, so we use the same
|
||||
# length but from a larger character set just because we can.
|
||||
# We want a unique build ID so a fresh build is started for each run instead
|
||||
# of potentially reusing an old build. See https://github.com/certbot/certbot/pull/8719
|
||||
# and https://github.com/snapcore/snapcraft/pull/3554 for more info.
|
||||
#
|
||||
# In the hope that one day you can again set a build ID, we will modify
|
||||
# the directory by creating a file containing a build ID that conforms
|
||||
# to the shape of snapcraft's build ID: using a MD5 hash represented as a
|
||||
# 32 character hex string (we use a larger character set).
|
||||
|
||||
random_string = ''.join(random.choice(string.ascii_lowercase + string.digits)
|
||||
for _ in range(32))
|
||||
build_id = f'snapcraft-{target}-{random_string}'
|
||||
# place random string in build_id file inside `workspace` directory
|
||||
with open(join(workspace, 'build_id'), 'w') as build_id_file:
|
||||
build_id_file.write(random_string)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tempdir:
|
||||
environ = os.environ.copy()
|
||||
environ['XDG_CACHE_HOME'] = tempdir
|
||||
process = subprocess.Popen([
|
||||
'snapcraft', 'remote-build', '--launchpad-accept-public-upload',
|
||||
'--build-for', ','.join(archs), '--build-id', build_id],
|
||||
'--build-for', ','.join(archs)],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||||
universal_newlines=True, env=environ, cwd=workspace)
|
||||
|
||||
@@ -103,6 +109,10 @@ def _build_snap(
|
||||
workspace = CERTBOT_DIR
|
||||
else:
|
||||
workspace = join(CERTBOT_DIR, target)
|
||||
# init and commit git repo in workspace
|
||||
subprocess.run(['git', 'init'], capture_output=True, check=True, cwd=workspace)
|
||||
subprocess.run(['git', 'add', '-A'], capture_output=True, check=True, cwd=workspace)
|
||||
subprocess.run(['git', 'commit', '-m', 'init'], capture_output=True, check=True, cwd=workspace)
|
||||
|
||||
build_success = False
|
||||
retry = 3
|
||||
@@ -115,7 +125,7 @@ def _build_snap(
|
||||
print(f'Build {target} for {",".join(archs)} (attempt {4-retry}/3) ended with '
|
||||
f'exit code {exit_code}.')
|
||||
|
||||
failed_archs = [arch for arch in archs if status[target][arch] != 'Successfully built']
|
||||
failed_archs = [arch for arch in archs if status[target][arch] != 'Succeeded']
|
||||
# If the command failed or any architecture wasn't built
|
||||
# successfully, let's try to print all the output about the problem
|
||||
# that we can.
|
||||
@@ -147,17 +157,17 @@ def _build_snap(
|
||||
def _extract_state(project: str, output: str, status: Dict[str, Dict[str, str]]) -> None:
|
||||
state = status[project]
|
||||
|
||||
if "Sending build data to Launchpad..." in output:
|
||||
if "Starting new build" in output:
|
||||
for arch in state.keys():
|
||||
state[arch] = "Sending build data"
|
||||
state[arch] = "Starting new build"
|
||||
|
||||
match = re.match(r'^.*arch=(\w+)\s+state=([\w ]+).*$', output)
|
||||
match = re.match(r'^(\w+): (\w+)$', output)
|
||||
if match:
|
||||
arch = match.group(1)
|
||||
state[arch] = match.group(2)
|
||||
arch = match.group(2)
|
||||
state[arch] = match.group(1)
|
||||
|
||||
# You need to reassign the value of status[project] here (rather than doing
|
||||
# something like status[project][arch] = match.group(2)) for the state change
|
||||
# something like status[project][arch] = match.group(1)) for the state change
|
||||
# to propagate to other processes. See
|
||||
# https://docs.python.org/3.8/library/multiprocessing.html#proxy-objects for
|
||||
# more info.
|
||||
@@ -187,18 +197,18 @@ def _dump_status(
|
||||
def _dump_failed_build_logs(
|
||||
target: str, archs: Set[str], status: Dict[str, Dict[str, str]],
|
||||
workspace: str) -> None:
|
||||
logs_list = glob.glob(join(workspace, f'snapcraft-{target}-*.txt'))
|
||||
for arch in archs:
|
||||
result = status[target][arch]
|
||||
|
||||
if result != 'Successfully built':
|
||||
if result != 'Succeeded':
|
||||
failures = True
|
||||
|
||||
build_output_name = _snap_log_name(target, arch)
|
||||
build_output_path = join(workspace, build_output_name)
|
||||
if not exists(build_output_path):
|
||||
build_output_path = [log_name for log_name in logs_list if arch in log_name]
|
||||
if not build_output_path:
|
||||
build_output = f'No output has been dumped by snapcraft remote-build.'
|
||||
else:
|
||||
with open(build_output_path) as file_h:
|
||||
with open(build_output_path[0]) as file_h:
|
||||
build_output = file_h.read()
|
||||
|
||||
print(f'Output for failed build target={target} arch={arch}')
|
||||
@@ -240,10 +250,6 @@ def main():
|
||||
subprocess.run(['tools/snap/generate_dnsplugins_all.sh'],
|
||||
check=True, cwd=CERTBOT_DIR)
|
||||
|
||||
# Use the legacy remote launchpad build until
|
||||
# https://github.com/certbot/certbot/issues/9890 is fixed
|
||||
os.environ['SNAPCRAFT_REMOTE_BUILD_STRATEGY'] = 'force-fallback'
|
||||
|
||||
print('Start remote snap builds...')
|
||||
print(f' - archs: {", ".join(archs)}')
|
||||
print(f' - projects: {", ".join(sorted(targets))}')
|
||||
|
||||
@@ -25,7 +25,7 @@ cb_required=\$(grep -oP "version = '\K.*(?=')" \$SNAP/setup.py)
|
||||
|
||||
\$SNAP/bin/python3 -c "import sys; from packaging import version; sys.exit(1) if\
|
||||
version.parse('\$cb_installed') < version.parse('\$cb_required') else sys.exit(0)" || exit_code=\$?
|
||||
if [ "\$exit_code" -eq 1 ]; then
|
||||
if [ "\$exit_code" = "1" ]; then
|
||||
echo "Certbot is version \$cb_installed but needs to be at least \$cb_required before" \\
|
||||
"this plugin can be updated; will try again on next refresh."
|
||||
exit 1
|
||||
|
||||
@@ -16,7 +16,7 @@ summary: ${DESCRIPTION}
|
||||
description: ${DESCRIPTION}
|
||||
confinement: strict
|
||||
grade: stable
|
||||
base: core20
|
||||
base: core24
|
||||
adopt-info: ${PLUGIN}
|
||||
|
||||
parts:
|
||||
@@ -24,8 +24,8 @@ parts:
|
||||
plugin: python
|
||||
source: .
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
snapcraftctl set-version \`grep ^version \$SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]"\`
|
||||
craftctl default
|
||||
craftctl set version=\$(grep ^version \$SNAPCRAFT_PART_SRC/setup.py | cut -f2 -d= | tr -d "'[:space:]")
|
||||
build-environment:
|
||||
# We set this environment variable while building to try and increase the
|
||||
# stability of fetching the rust crates needed to build the cryptography
|
||||
@@ -53,7 +53,7 @@ parts:
|
||||
source: .
|
||||
stage: [setup.py, certbot-shared]
|
||||
override-pull: |
|
||||
snapcraftctl pull
|
||||
craftctl default
|
||||
mkdir -p \$SNAPCRAFT_PART_SRC/certbot-shared
|
||||
|
||||
slots:
|
||||
@@ -61,7 +61,7 @@ slots:
|
||||
interface: content
|
||||
content: certbot-1
|
||||
read:
|
||||
- \$SNAP/lib/python3.8/site-packages
|
||||
- \$SNAP/lib/python3.12/site-packages
|
||||
|
||||
plugs:
|
||||
certbot-metadata:
|
||||
|
||||
Reference in New Issue
Block a user