From ebf91c122841b7f4fc4eb90b7af28d884dea678b Mon Sep 17 00:00:00 2001 From: Zack Brady Date: Fri, 6 Mar 2026 09:53:13 -0500 Subject: [PATCH] release v1.4.2 (#525) * fix: handling of file referenced dependencies without repository field (#514) co-authored-by: devleitner * bump go.opentelemetry.io/otel/sdk (#520) bumps the go_modules group with 1 update in the / directory: [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go). updates `go.opentelemetry.io/otel/sdk` from 1.39.0 to 1.40.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.39.0...v1.40.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/sdk dependency-version: 1.40.0 dependency-type: indirect dependency-group: go_modules ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * dev.md file (#521) * smaller changes and updates for v1.4.2 release (#524) * smaller changes and updates for v1.4.2 release * removed unused env variable --------- Signed-off-by: dependabot[bot] Co-authored-by: devLeitner <87783219+devLeitner@users.noreply.github.com> Co-authored-by: devleitner Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Camryn Carter --- .github/workflows/pages.yaml | 4 +- .github/workflows/release.yaml | 14 +- .github/workflows/testdata.yaml | 2 +- .github/workflows/tests.yaml | 16 +- .goreleaser.yaml | 3 +- DEVELOPMENT.md | 155 ++++++++++++++++++ README.md | 8 +- cmd/hauler/cli/store/add.go | 2 +- go.mod | 10 +- go.sum | 24 +-- ...chart-with-file-dependency-chart-1.0.0.tgz | Bin 691 -> 774 bytes 11 files changed, 199 insertions(+), 39 deletions(-) create mode 100644 DEVELOPMENT.md diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index 7b36333..bdef9c7 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -29,7 +29,7 @@ jobs: run: rm -rf /opt/hostedtoolcache - name: Checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -42,7 +42,7 @@ jobs: uses: actions/configure-pages@v5 - name: Upload Pages Artifacts - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: path: './static' diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7f521d7..8377aae 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -17,7 +17,7 @@ jobs: run: rm -rf /opt/hostedtoolcache - name: Checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -27,33 +27,33 @@ jobs: git config user.email "github-actions[bot]@users.noreply.github.com" - name: Set Up Go - uses: actions/setup-go@v6.1.0 + uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true - name: Set Up QEMU - uses: docker/setup-qemu-action@v3.7.0 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3.11.1 + uses: docker/setup-buildx-action@v3 - name: Authenticate to GitHub Container Registry - uses: docker/login-action@v3.6.0 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Authenticate to DockerHub Container Registry - uses: docker/login-action@v3.6.0 + uses: docker/login-action@v3 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v6.4.0 + uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser version: "~> v2" diff --git a/.github/workflows/testdata.yaml b/.github/workflows/testdata.yaml index e11f0f7..5854cd7 100644 --- a/.github/workflows/testdata.yaml +++ b/.github/workflows/testdata.yaml @@ -14,7 +14,7 @@ jobs: run: rm -rf /opt/hostedtoolcache - name: Checkout Repository - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6 - name: Fetch Hauler Binary run: curl -sfL https://get.hauler.dev | bash diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 1e8c1e0..599419b 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -20,7 +20,7 @@ jobs: run: rm -rf /opt/hostedtoolcache - name: Checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -30,13 +30,13 @@ jobs: git config user.email "github-actions[bot]@users.noreply.github.com" - name: Set Up Go - uses: actions/setup-go@v6.1.0 + uses: actions/setup-go@v6 with: go-version-file: go.mod check-latest: true - name: Install Go Releaser - uses: goreleaser/goreleaser-action@v6.4.0 + uses: goreleaser/goreleaser-action@v6 with: install-only: true @@ -51,13 +51,13 @@ jobs: make build-all - name: Upload Hauler Binaries - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@v6 with: name: hauler-binaries path: dist/* - name: Upload Coverage Report - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@v6 with: name: coverage-report path: coverage.out @@ -73,7 +73,7 @@ jobs: run: rm -rf /opt/hostedtoolcache - name: Checkout - uses: actions/checkout@v6.0.1 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -89,7 +89,7 @@ jobs: sudo apt-get install -y tree - name: Download Artifacts - uses: actions/download-artifact@v6.0.0 + uses: actions/download-artifact@v6 with: name: hauler-binaries path: dist @@ -468,7 +468,7 @@ jobs: hauler store info - name: Upload Hauler Report - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@v6 with: name: hauler-report path: hauler-report.txt diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 0859d49..a0ac032 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -15,7 +15,6 @@ release: env: - vpkg=hauler.dev/go/hauler/internal/version - - cosign_version=v2.2.3+carbide.3 builds: - dir: ./cmd/hauler/. @@ -88,4 +87,4 @@ dockers_v2: "org.opencontainers.image.name": "{{.ProjectName}}-debug" "org.opencontainers.image.revision": "{{.FullCommit}}" "org.opencontainers.image.source": "{{.GitURL}}" - "org.opencontainers.image.version": "{{.Version}}" \ No newline at end of file + "org.opencontainers.image.version": "{{.Version}}" diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..dde27a7 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,155 @@ +# Development Guide + +This document covers how to build `hauler` locally and how the project's branching strategy works. + +It's intended for contributors making code changes or maintainers managing releases. + +--- + +## Local Build + +### Prerequisites + +- **Git** - version control of the repository +- **Go** — check `go.mod` for the minimum required version +- **Make** - optional... for common commands used for builds +- **Docker** - optional... for container image builds + +### Clone the Repository + +```bash +git clone https://github.com/hauler-dev/hauler.git +cd hauler +``` + +### Build the Binary + +Using `make`... + +```bash +# run this command from the project root +make build + +# the compiled binary will be output to a directory structure and you can run it directly... +./dist/hauler_linux_amd64_v1/hauler +./dist/hauler_linux_arm64_v8.0/hauler +./dist/hauler_darwin_amd64_v1/hauler +./dist/hauler_darwin_arm64_v8.0/hauler +./dist/hauler_windows_amd64_v1/hauler.exe +./dist/hauler_windows_arm64_v8.0/hauler.exe +``` + +Using `go`... + +```bash +# run this command from the project root +go build -o hauler ./cmd/hauler + +# the compiled binary will be output to the project root and you can run it directly... +./hauler version +``` + +### Run Tests + +Using `make`... + +```bash +make test +``` + +Using `go`... + +```bash +go test ./... +``` + +### Useful Tips + +- The `--store` flag defaults to `./store` in the current working directory during local testing, so running `./hauler store add ...` from the project root is safe and self-contained. Use `rm -rf store` in the working directory to clear. +- Set `--log-level debug` when developing to get verbose output. + +--- + +## Branching Strategy + +Hauler uses a **main-first, release branch** model. All development flows through `main` and `release/x.x` branches are maintained for each minor version to support patching older release lines in parallel. + +### Branch Structure + +``` +main ← source of truth, all development targets here +release/1.3 ← 1.3.x patch line +release/1.4 ← 1.4.x patch line +``` + +Release tags (`v1.4.1`, `v1.3.2`, etc.) are always cut from the corresponding `release/X.Y` branch, never directly from `main`. + +### Where to Target Your Changes + +All pull requests should target `main` by default and maintainers are responsible for cherry picking fixes onto release branches as part of the patch release process. + +| Change Type | Target branch | +| :---------: | :-----------: | +| New features | `main` | +| Bug fixes | `main` | +| Security patches | `main` (expedited backport to affected branches) | +| Release-specific fix (see below) | `release/X.Y` directly | + +### Creating a New Release Branch + +When `main` is ready to ship a new minor version, a release branch is cut: + +```bash +git checkout main +git pull origin main +git checkout -b release/1.4 +git push origin release/1.4 +``` + +The first release is then tagged from that branch: + +```bash +git tag v1.4.0 +git push origin v1.4.0 +``` + +Development on `main` immediately continues toward the next minor. + +### Backporting a Fix to a Release Branch + +When a bug fix merged to `main` also needs to apply to an active release line, cherry-pick the commit onto the release branch and open a PR targeting it: + +```bash +git checkout release/1.3 +git pull origin release/1.3 +git checkout -b backport/fix-description-to-1.3 +git cherry-pick +git push origin backport/fix-description-to-1.3 +``` + +Open a PR targeting `release/1.3` and reference the original PR in the description. If the cherry-pick doesn't apply cleanly, resolve conflicts and note them in the PR. + +### Fixes That Only Apply to an Older Release Line + +Sometimes a bug exists in an older release but the relevant code has been removed or significantly changed in `main` — making a forward-port unnecessary or nonsensical. In these cases, it's acceptable to open a PR directly against the affected `release/X.Y` branch. + +When doing this, the PR description must explain: + +- Which versions are affected +- Why the fix does not apply to `main` or newer release lines (e.g., "this code path was removed in 1.4 when X was refactored") + +This keeps the history auditable and prevents future contributors from wondering why the fix never made it forward. + +### Summary + +``` + ┌─────────────────────────────────────────► main (next minor) + │ + │ cherry-pick / backport PRs + │ ─────────────────────────► release/1.4 (v1.4.0, v1.4.1 ...) + │ + │ ─────────────────────────► release/1.3 (v1.3.0, v1.3.1 ...) + │ + │ direct fix (older-only bug) + │ ─────────────────────────► release/1.2 (critical fixes only) +``` diff --git a/README.md b/README.md index 23dc051..4647473 100644 --- a/README.md +++ b/README.md @@ -19,23 +19,29 @@ For more information, please review the **[Hauler Documentation](https://hauler. - `!!! WARNING !!! [--products] will be updating its default registry in a future release...` - `!!! WARNING !!! [--product-registry] will be updating its default registry in a future release...` -### In Hauler v1.2.0... +### From older releases... - Upgraded the `apiVersion` to `v1` from `v1alpha1` - Users are able to use `v1` and `v1alpha1`, but `v1alpha1` is now deprecated and will be removed in a future release. We will update the community when we fully deprecate and remove the functionality of `v1alpha1` - Users will see logging notices when using the old `apiVersion` such as... - `!!! DEPRECATION WARNING !!! apiVersion [v1alpha1] will be removed in a future release...` + --- + - Updated the behavior of `hauler store load` to default to loading a `haul` with the name of `haul.tar.zst` and requires the flag of `--filename/-f` to load a `haul` with a different name - Users can load multiple `hauls` by specifying multiple flags of `--filename/-f` - updated command usage: `hauler store load --filename hauling-hauls.tar.zst` - previous command usage (do not use): `hauler store load hauling-hauls.tar.zst` + --- + - Updated the behavior of `hauler store sync` to default to syncing a `manifest` with the name of `hauler-manifest.yaml` and requires the flag of `--filename/-f` to sync a `manifest` with a different name - Users can sync multiple `manifests` by specifying multiple flags of `--filename/-f` - updated command usage: `hauler store sync --filename hauling-hauls-manifest.yaml` - previous command usage (do not use): `hauler store sync --files hauling-hauls-manifest.yaml` + --- + Please review the documentation for any additional [Known Limits, Issues, and Notices](https://docs.hauler.dev/docs/known-limits)! ## Installation diff --git a/cmd/hauler/cli/store/add.go b/cmd/hauler/cli/store/add.go index f5432c5..97ec6c9 100644 --- a/cmd/hauler/cli/store/add.go +++ b/cmd/hauler/cli/store/add.go @@ -521,7 +521,7 @@ func storeChart(ctx context.Context, s *store.Layout, cfg v1.Chart, opts *flags. var depCfg v1.Chart var err error - if strings.HasPrefix(dep.Repository, "file://") { + if strings.HasPrefix(dep.Repository, "file://") || dep.Repository == "" { subchartPath := filepath.Join(chartPath, "charts", dep.Name) depCfg = v1.Chart{Name: subchartPath, RepoURL: "", Version: ""} diff --git a/go.mod b/go.mod index ccb5e4a..a9da2ac 100644 --- a/go.mod +++ b/go.mod @@ -316,10 +316,10 @@ require ( go.mongodb.org/mongo-driver v1.17.6 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect - go.opentelemetry.io/otel v1.39.0 // indirect - go.opentelemetry.io/otel/metric v1.39.0 // indirect - go.opentelemetry.io/otel/sdk v1.39.0 // indirect - go.opentelemetry.io/otel/trace v1.39.0 // indirect + go.opentelemetry.io/otel v1.40.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/sdk v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect @@ -329,7 +329,7 @@ require ( golang.org/x/mod v0.31.0 // indirect golang.org/x/net v0.48.0 // indirect golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect golang.org/x/term v0.38.0 // indirect golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.14.0 // indirect diff --git a/go.sum b/go.sum index 521b434..0d845ff 100644 --- a/go.sum +++ b/go.sum @@ -1027,22 +1027,22 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0/go.mod h1:Rp0EXBm5tfnv0WL+ARyO/PHBEaEAT8UUHQ6AGJcSq6c= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= +go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= +go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= +go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.step.sm/crypto v0.75.0 h1:UAHYD6q6ggYyzLlIKHv1MCUVjZIesXRZpGTlRC/HSHw= @@ -1203,8 +1203,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= -golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= diff --git a/testdata/chart-with-file-dependency-chart-1.0.0.tgz b/testdata/chart-with-file-dependency-chart-1.0.0.tgz index 30d96ee1da172a04345a37900b8f865aef35b51d..76f8107c69d39b8bebb5daf4929eea09ba9bd03e 100644 GIT binary patch delta 727 zcmV;|0x12n1%?KYJAatVZ>%;H#%Il6VP)BB;Mn*9UR7$BT~^&6@F9aP0|>jR=D)9) zFw+UCLPDzPy}kSvAmJAefBrsG9&iZzKkIPVS9L>sM?JNU+VZqN7bQQB$M}TDX15jq z04?SD3;^>pq=N6b;!-KYL6{wIlN!BauzJJ~@P`jL?BLU5&3_;68v*~A;VlcBcTGRGp>b7 zkw=fz(tv@SWe);`-hmo z)cCQ0jqR@`zNgYYuOOpSd&|;@F;5MZp&Op-A2F1NUvD~i*#%>lxi?k6xr>qJMay|x z#xA!oQg&^?x~1V-e?NbcXX+z9l4XzO5Z7JeY9EHKA@7p{J^eH-ZKgsarE*n41(K{} zVXy$wRDb2UFq(1=Mj=U|GKrNInJy4AFbbS@6{)XirCQYg`RJ1|#jV{7Ea@LiI@3Sb zf^Yi22ebTt6WQNL+GAqpU(qDqSj~s@zcLFf`oB^${YxX$P5<{`rTm3QlZd|fL8z_S0#xlsQbB{u!vgMaq_vo_uc0Al;q_CMic z`d=3SmiPa&|NlaPfldGSV6Fd8?)f?ZoC`jc0H&_jM1ZTOZy8`?V`F21zXAXN|NnBK JCv^ZI003+IbprqZ delta 643 zcmV-}0(||32D1f_JAaqKa=SJV#yRs8np``Wl@Jo>)S33!W2g58Ew&~Y7^J4-x9?yF z$8l%kgmm2g6MhGCSnUdozWtVZhhs?oa$%P=uBF7%K%J$oJ|xFb`pfjYIpDsHmI45v zq&!{$;Q9(eiiqc2W=e7Z9Rb&w77>HRJAQyaeZVn-Pw#d8aDP7tIJiG(^ses=dlK>a z^*iz=PFRO~GOXUY*2avDH1ytuemod9ofea(n@u`LpXNGZ0~?6v)VI%991a5+hQrXh z8iVV*_*{n{>-^XM(AVaj`fvOCaq%9v^q+A#>mM{1NByf+|99bE6ufm?^1(2_Ly;>} zl&FOkd2Nxb)PIs{1h8e^SX=WFni8qf4bKE26j(~DB{U#a!Ij7}_LD~ z35bMezjI}TFga{^k%>&oqWlTC0eDzD#R6{XKhS=@4==2<1qO2iN}wwvxfb8e%6+!_z2divD`TwX>-PHf_*PnX+!jFMl`UidC{~#j}TuZ&`{~lb; z|Cjdv#$+zm$^47(G5s$a25$R5fAN115r`br>i>6Pq5sdH0ROQ6Q{Xf1KbKx${&VVk dz5iwXceMVMm6dPK-vIys|Nr&{X;=Ul0078nP>lcp