Skip to content

Commit 7462700

Browse files
authored
Merge branch 'main' into mattm-refactor-ticker
2 parents 4b9458f + a1cf84f commit 7462700

File tree

137 files changed

+3414
-2068
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+3414
-2068
lines changed

.github/workflows/release.yml

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,42 @@
11
# Build the Boulder Debian package on tag push, and attach it to a GitHub
22
# release.
33
#
4-
# Keep in sync with try-release.yml, with the exception that try-release.yml can
5-
# have multiple entries in its matrix but this should only have one.
4+
# Keep the GO_VERSION matrix and the container-building steps in sync with
5+
# try-release.yml.
66
name: Build release
77
on:
88
push:
99
tags:
1010
- '**'
1111

1212
jobs:
13+
draft-release:
14+
runs-on: ubuntu-24.04
15+
permissions:
16+
contents: write
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
persist-credentials: false
21+
fetch-depth: '0' # Needed for verify-release-ancestry.sh to see origin/main
22+
23+
- name: Verify release ancestry
24+
run: ./tools/verify-release-ancestry.sh "$GITHUB_SHA"
25+
26+
- name: Create draft release
27+
env:
28+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
# https://cli.github.com/manual/gh_release_create
30+
run: gh release create --draft --generate-notes "${GITHUB_REF_NAME}"
31+
1332
push-release:
33+
needs: draft-release
1434
strategy:
1535
fail-fast: false
1636
matrix:
1737
GO_VERSION:
1838
- "1.25.2"
39+
- "1.25.3"
1940
runs-on: ubuntu-24.04
2041
permissions:
2142
contents: write
@@ -26,47 +47,55 @@ jobs:
2647
persist-credentials: false
2748
fetch-depth: '0' # Needed for verify-release-ancestry.sh to see origin/main
2849

29-
- name: Verify release ancestry
30-
run: ./tools/verify-release-ancestry.sh "$GITHUB_SHA"
31-
3250
- name: Build Boulder container and .deb
3351
id: build
3452
env:
3553
GO_VERSION: ${{ matrix.GO_VERSION }}
3654
run: ./tools/container-build.sh
3755

3856
- name: Tag Boulder container
39-
run: docker tag boulder "ghcr.io/letsencrypt/boulder:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
57+
run: docker tag boulder "ghcr.io/letsencrypt/boulder:${GITHUB_REF_NAME}-go${{ matrix.GO_VERSION }}"
4058

4159
- name: Compute checksums
4260
id: checksums
4361
# The files listed on this line must be identical to the files uploaded
4462
# in the last step.
4563
run: sha256sum boulder*.deb boulder*.tar.gz >| boulder-${{ matrix.GO_VERSION }}.$(date +%s)-$(git rev-parse --short=8 HEAD).checksums.txt
4664

47-
- name: Create release
48-
env:
49-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50-
# https://cli.github.com/manual/gh_release_create
51-
run: gh release create --generate-notes "${GITHUB_REF_NAME}"
52-
continue-on-error: true
53-
5465
- name: Upload release files
5566
env:
5667
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5768
# https://cli.github.com/manual/gh_release_upload
5869
run: gh release upload "${GITHUB_REF_NAME}" boulder*.deb boulder*.tar.gz boulder*.checksums.txt
5970

6071
- name: Build ct-test-srv container
61-
run: docker buildx build . --build-arg "GO_VERSION=${{ matrix.GO_VERSION }}" -f test/ct-test-srv/Dockerfile -t "ghcr.io/letsencrypt/ct-test-srv:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
72+
run: docker buildx build . --build-arg "GO_VERSION=${{ matrix.GO_VERSION }}" -f test/ct-test-srv/Dockerfile -t "ghcr.io/letsencrypt/ct-test-srv:${GITHUB_REF_NAME}-go${{ matrix.GO_VERSION }}"
6273

63-
- name: Login to ghcr.io
64-
run: printenv GITHUB_TOKEN | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
65-
env:
66-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
74+
- name: Login to GitHub Container Registry
75+
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
76+
with:
77+
registry: ghcr.io
78+
username: ${{ github.actor }}
79+
password: ${{ secrets.GITHUB_TOKEN }}
6780

6881
- name: Push Boulder container
69-
run: docker push "ghcr.io/letsencrypt/boulder:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
82+
run: docker push "ghcr.io/letsencrypt/boulder:${GITHUB_REF_NAME}-go${{ matrix.GO_VERSION }}"
7083

7184
- name: Push ct-test-srv container
72-
run: docker push "ghcr.io/letsencrypt/ct-test-srv:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
85+
run: docker push "ghcr.io/letsencrypt/ct-test-srv:${GITHUB_REF_NAME}-go${{ matrix.GO_VERSION }}"
86+
87+
publish-release:
88+
needs: push-release
89+
runs-on: ubuntu-24.04
90+
permissions:
91+
contents: write
92+
steps:
93+
- uses: actions/checkout@v4
94+
with:
95+
persist-credentials: false
96+
97+
- name: Publish release
98+
env:
99+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100+
# https://cli.github.com/manual/gh_release_edit
101+
run: gh release edit --draft=false "${GITHUB_REF_NAME}"

.github/workflows/try-release.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# Try building the Boulder Debian package on every PR and push to main.
2-
# This is to make sure the actual release job will succeed when we tag a
3-
# release.
4-
# Keep in sync with release.yml
1+
# Try building the Boulder Debian package on every PR and push to main. This is
2+
# to make sure the actual release job will succeed when we tag a release.
3+
#
4+
# Keep the GO_VERSION matrix and the container-building steps in sync with
5+
# release.yml.
56
name: Try release
67
on:
78
push:
@@ -20,6 +21,7 @@ jobs:
2021
matrix:
2122
GO_VERSION:
2223
- "1.25.2"
24+
- "1.25.3"
2325
runs-on: ubuntu-24.04
2426
steps:
2527
- uses: actions/checkout@v4

README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,43 +112,44 @@ docker compose up
112112
To run our standard battery of tests (lints, unit, integration):
113113

114114
```shell
115-
docker compose run --use-aliases boulder ./test.sh
115+
./t.sh
116116
```
117117

118118
To run all unit tests:
119119

120120
```shell
121-
docker compose run --use-aliases boulder ./test.sh --unit
121+
./t.sh -u
122122
```
123123

124124
To run specific unit tests (example is of the ./va directory):
125125

126126
```shell
127-
docker compose run --use-aliases boulder ./test.sh --unit --filter=./va
127+
./t.sh -u -p ./va
128128
```
129129

130130
To run all integration tests:
131131

132132
```shell
133-
docker compose run --use-aliases boulder ./test.sh --integration
133+
./t.sh -i
134134
```
135135

136136
To run unit tests and integration tests with coverage:
137137

138138
```shell
139-
docker compose run --use-aliases boulder ./test.sh --unit --integration --coverage --coverage-dir=./test/coverage/mytestrun
139+
./t.sh -ui -c --coverage-dir=./test/coverage/mytestrun
140140
```
141141

142142
To run specific integration tests (example runs TestGenerateValidity and TestWFECORS):
143143

144144
```shell
145-
docker compose run --use-aliases boulder ./test.sh --filter TestGenerateValidity/TestWFECORS
145+
./t.sh -i -f TestGenerateValidity/TestWFECORS
146146
```
147147

148-
To get a list of available integration tests:
148+
To do any of the above, but using the "config-next" configuration, which
149+
represents a likely future state (e.g. including new feature flags):
149150

150151
```shell
151-
docker compose run --use-aliases boulder ./test.sh --list-integration-tests
152+
./tn.sh -your -options -here
152153
```
153154

154155
The configuration in docker-compose.yml mounts your boulder checkout at
@@ -186,7 +187,13 @@ docker compose run --use-aliases -e FAKE_DNS=172.17.0.1 --service-ports boulder
186187

187188
Running tests without the `./test.sh` wrapper:
188189

189-
Run all unit tests
190+
Run unit tests locally, without docker (only works for some directories):
191+
192+
```shell
193+
go test ./issuance/...
194+
```
195+
196+
Run all unit tests:
190197

191198
```shell
192199
docker compose run --use-aliases boulder go test -p 1 ./...

bdns/dns.go

Lines changed: 12 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ package bdns
33
import (
44
"context"
55
"crypto/tls"
6-
"encoding/base64"
76
"errors"
87
"fmt"
98
"io"
109
"net"
1110
"net/http"
1211
"net/netip"
13-
"net/url"
1412
"slices"
1513
"strconv"
1614
"strings"
@@ -48,10 +46,9 @@ type impl struct {
4846
clk clock.Clock
4947
log blog.Logger
5048

51-
queryTime *prometheus.HistogramVec
52-
totalLookupTime *prometheus.HistogramVec
53-
timeoutCounter *prometheus.CounterVec
54-
idMismatchCounter *prometheus.CounterVec
49+
queryTime *prometheus.HistogramVec
50+
totalLookupTime *prometheus.HistogramVec
51+
timeoutCounter *prometheus.CounterVec
5552
}
5653

5754
var _ Client = &impl{}
@@ -118,14 +115,6 @@ func New(
118115
},
119116
[]string{"qtype", "type", "resolver", "isTLD"},
120117
)
121-
idMismatchCounter := prometheus.NewCounterVec(
122-
prometheus.CounterOpts{
123-
Name: "dns_id_mismatch",
124-
Help: "Counter of DNS ErrId errors sliced by query type and resolver",
125-
},
126-
[]string{"qtype", "resolver"},
127-
)
128-
stats.MustRegister(queryTime, totalLookupTime, timeoutCounter, idMismatchCounter)
129118
return &impl{
130119
dnsClient: client,
131120
servers: servers,
@@ -135,7 +124,6 @@ func New(
135124
queryTime: queryTime,
136125
totalLookupTime: totalLookupTime,
137126
timeoutCounter: timeoutCounter,
138-
idMismatchCounter: idMismatchCounter,
139127
log: log,
140128
}
141129
}
@@ -230,13 +218,11 @@ func (dnsClient *impl) exchangeOne(ctx context.Context, hostname string, qtype u
230218
result = dns.RcodeToString[rsp.Rcode]
231219
}
232220
if err != nil {
233-
logDNSError(dnsClient.log, chosenServer, hostname, m, rsp, err)
234-
if err == dns.ErrId {
235-
dnsClient.idMismatchCounter.With(prometheus.Labels{
236-
"qtype": qtypeStr,
237-
"resolver": chosenServerIP,
238-
}).Inc()
239-
}
221+
dnsClient.log.Infof("logDNSError chosenServer=[%s] hostname=[%s] queryType=[%s] err=[%s]",
222+
chosenServer,
223+
hostname,
224+
qtypeStr,
225+
err)
240226
}
241227
dnsClient.queryTime.With(prometheus.Labels{
242228
"qtype": qtypeStr,
@@ -273,10 +259,10 @@ func (dnsClient *impl) exchangeOne(ctx context.Context, hostname string, qtype u
273259
case r := <-ch:
274260
if r.err != nil {
275261
var isRetryable bool
276-
// According to the http package documentation, retryable
277-
// errors emitted by the http package are of type *url.Error.
278-
var urlErr *url.Error
279-
isRetryable = errors.As(r.err, &urlErr) && urlErr.Temporary()
262+
// Check if the error is a timeout error. Network errors
263+
// that can timeout implement the net.Error interface.
264+
var netErr net.Error
265+
isRetryable = errors.As(r.err, &netErr) && netErr.Timeout()
280266
hasRetriesLeft := tries < dnsClient.maxTries
281267
if isRetryable && hasRetriesLeft {
282268
tries++
@@ -469,68 +455,6 @@ func (dnsClient *impl) LookupCAA(ctx context.Context, hostname string) ([]*dns.C
469455
return CAAs, response, ResolverAddrs{resolver}, nil
470456
}
471457

472-
// logDNSError logs the provided err result from making a query for hostname to
473-
// the chosenServer. If the err is a `dns.ErrId` instance then the Base64
474-
// encoded bytes of the query (and if not-nil, the response) in wire format
475-
// is logged as well. This function is called from exchangeOne only for the case
476-
// where an error occurs querying a hostname that indicates a problem between
477-
// the VA and the chosenServer.
478-
func logDNSError(
479-
logger blog.Logger,
480-
chosenServer string,
481-
hostname string,
482-
msg, resp *dns.Msg,
483-
underlying error) {
484-
// We don't expect logDNSError to be called with a nil msg or err but
485-
// if it happens return early. We allow resp to be nil.
486-
if msg == nil || len(msg.Question) == 0 || underlying == nil {
487-
return
488-
}
489-
queryType := dns.TypeToString[msg.Question[0].Qtype]
490-
491-
// If the error indicates there was a query/response ID mismatch then we want
492-
// to log more detail.
493-
if underlying == dns.ErrId {
494-
packedMsgBytes, err := msg.Pack()
495-
if err != nil {
496-
logger.Errf("logDNSError failed to pack msg: %v", err)
497-
return
498-
}
499-
encodedMsg := base64.StdEncoding.EncodeToString(packedMsgBytes)
500-
501-
var encodedResp string
502-
var respQname string
503-
if resp != nil {
504-
packedRespBytes, err := resp.Pack()
505-
if err != nil {
506-
logger.Errf("logDNSError failed to pack resp: %v", err)
507-
return
508-
}
509-
encodedResp = base64.StdEncoding.EncodeToString(packedRespBytes)
510-
if len(resp.Answer) > 0 && resp.Answer[0].Header() != nil {
511-
respQname = resp.Answer[0].Header().Name
512-
}
513-
}
514-
515-
logger.Infof(
516-
"logDNSError ID mismatch chosenServer=[%s] hostname=[%s] respHostname=[%s] queryType=[%s] msg=[%s] resp=[%s] err=[%s]",
517-
chosenServer,
518-
hostname,
519-
respQname,
520-
queryType,
521-
encodedMsg,
522-
encodedResp,
523-
underlying)
524-
} else {
525-
// Otherwise log a general DNS error
526-
logger.Infof("logDNSError chosenServer=[%s] hostname=[%s] queryType=[%s] err=[%s]",
527-
chosenServer,
528-
hostname,
529-
queryType,
530-
underlying)
531-
}
532-
}
533-
534458
type dohExchanger struct {
535459
clk clock.Clock
536460
hc http.Client

0 commit comments

Comments
 (0)