Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ jobs:
persist-credentials: false
- name: artifacthub.io/images matches values.yaml
run: hack/chart-images.sh --check
- name: Every Appwrite version named matches appVersion
run: make check-versions

artifacthub:
name: Artifact Hub lint
Expand Down
35 changes: 27 additions & 8 deletions .github/workflows/test-install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ concurrency:

jobs:
install:
name: ${{ matrix.scenario }} (k8s ${{ matrix.kubernetes }})${{ matrix.upgrade-from && format(' upgrade from chart {0}', matrix.upgrade-from) || '' }}
name: ${{ matrix.scenario }} (k8s ${{ matrix.kubernetes }})${{ matrix.upgrade-from && ' upgrade from the latest release' || '' }}
runs-on: >-
${{ (github.event_name != 'pull_request'
|| github.event.pull_request.head.repo.full_name == github.repository)
Expand All @@ -52,12 +52,12 @@ jobs:
kubernetes: v1.37.0
- scenario: grouped-workers
kubernetes: v1.37.0
# Install a published chart release with its own defaults and
# Install the newest published chart with its own defaults and
# Appwrite version, then upgrade to this chart's: the chart upgrade
# and Appwrite's data migration.
# and Appwrite's data migration, as users will run them.
- scenario: default
kubernetes: v1.37.0
upgrade-from: 2.1.0
upgrade-from: latest
# PostgreSQL, Redis and ClickHouse outside the release.
- scenario: external-dbs
kubernetes: v1.37.0
Expand All @@ -80,6 +80,26 @@ jobs:
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: v4.3.0
- name: Versions under test
env:
GH_TOKEN: ${{ github.token }}
UPGRADE: ${{ matrix.upgrade-from }}
run: |
app_version=$(awk '/^appVersion:/ {gsub(/"/, "", $2); print $2}' charts/appwrite/Chart.yaml)
echo "APP_VERSION=${app_version}" >> "$GITHUB_ENV"
echo "Appwrite ${app_version}"
if [[ "$UPGRADE" == latest ]]; then
# Highest chart version with a release; the release workflow
# creates it only after the chart is in the registry. A release
# of this very commit (the release workflow can finish first on a
# push to main) would upgrade the chart to itself, so it's skipped.
from=$(gh api "repos/${GITHUB_REPOSITORY}/releases?per_page=100" \
--jq '.[] | select((.draft or .prerelease or .target_commitish == env.GITHUB_SHA) | not)
| .tag_name | select(startswith("appwrite-")) | ltrimstr("appwrite-")' | sort -V | tail -1)
[[ -n "$from" ]] || { echo "::error::No published chart release to upgrade from"; exit 1; }
echo "UPGRADE_FROM=${from}" >> "$GITHUB_ENV"
echo "::notice::Upgrading from chart ${from}"
fi
- uses: helm/kind-action@06c1ae10762d3b9c1644e7fe69596ae519e015a2 # v1.15.0
with:
cluster_name: appwrite
Expand Down Expand Up @@ -108,18 +128,17 @@ jobs:
# instead of as a 15-minute install timeout.
run: |
# shellcheck disable=SC2016 # expanded inside the pod
kubectl -n appwrite run dns-check --rm -i --restart=Never --image=docker.io/appwrite/appwrite:2.6.2 --command -- sh -c '
kubectl -n appwrite run dns-check --rm -i --restart=Never --image="docker.io/appwrite/appwrite:${APP_VERSION}" --command -- sh -c '
cat /etc/resolv.conf
ok=0
for host in postgres.external-dbs.svc.cluster.local postgres.external-dbs.svc postgres.external-dbs; do
if getent hosts "$host"; then echo "resolved $host"; else echo "FAILED $host"; ok=1; fi
done
exit $ok'
- name: Install chart ${{ matrix.upgrade-from }}
- name: Install the latest published chart
if: matrix.upgrade-from
env:
SCENARIO: ${{ matrix.scenario }}
UPGRADE_FROM: ${{ matrix.upgrade-from }}
run: |
helm upgrade --install appwrite oci://ghcr.io/appwrite/charts/appwrite --version "${UPGRADE_FROM}" \
-n appwrite --create-namespace -f "charts/appwrite/ci/${SCENARIO}-values.yaml" --wait --timeout 15m
Expand All @@ -131,7 +150,7 @@ jobs:
- name: Check the API runs the new version (the migration hook must succeed for the upgrade to pass)
if: matrix.upgrade-from
run: |
kubectl -n appwrite get deployment appwrite-api -o jsonpath='{.metadata.annotations.appwrite/version}' | grep -qx "$(awk '/^appVersion:/ {gsub(/"/, "", $2); print $2}' charts/appwrite/Chart.yaml)"
kubectl -n appwrite get deployment appwrite-api -o jsonpath='{.metadata.annotations.appwrite/version}' | grep -qx "$APP_VERSION"
- name: helm test
run: make helm-test
- name: Smoke test
Expand Down
15 changes: 15 additions & 0 deletions .github/workflows/upstream-drift.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,18 @@ jobs:
echo "https://github.com/appwrite/appwrite/compare/${current}...${latest}"
} > body.md
gh issue create --title "$title" --body-file body.md
# A failed scheduled run shows up nowhere else, and it hides the
# release it was looking at.
- name: Open an issue when the check fails
if: failure()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
title="Upstream drift check is failing"
number=$(gh issue list --state open --search "in:title \"${title}\"" --json number --jq '.[0].number // empty')
if [[ -n "$number" ]]; then
gh issue comment "$number" --body "Failed again: ${RUN_URL}"
else
gh issue create --title "$title" --body "The weekly check for new Appwrite releases failed, so a release may be going unnoticed. Run: ${RUN_URL}"
fi
15 changes: 8 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ The scenarios CI installs are the `charts/appwrite/ci/*-values.yaml` files.

| Workflow | When | What |
| --- | --- | --- |
| [Lint and test](.github/workflows/lint.yaml) | every pull request and push to `main` | `ct lint` and `helm lint --strict` for every `ci/` scenario, unit tests (Helm 3.18 and 4.3), kubeconform, `make examples`, generated files, `artifacthub.io/images`, `ah lint`, a `CHANGELOG.md` entry for chart changes and `make check-changes` |
| [Install](.github/workflows/test-install.yaml) | changes to `charts/`, `hack/`, the `Makefile` or the workflow | installs on kind per scenario, `helm test`, `hack/smoke.sh`, routes through Traefik, an upgrade from the previous Appwrite release, and a second upgrade that must keep credentials and pods; `Install result` sums up the scenarios |
| [Lint and test](.github/workflows/lint.yaml) | every pull request and push to `main` | `ct lint` and `helm lint --strict` for every `ci/` scenario, unit tests (Helm 3.18 and 4.3), kubeconform, `make examples`, generated files, `artifacthub.io/images`, Appwrite versions named in the docs (`make check-versions`), `ah lint`, a `CHANGELOG.md` entry for chart changes and `make check-changes` |
| [Install](.github/workflows/test-install.yaml) | changes to `charts/`, `hack/`, the `Makefile` or the workflow | installs on kind per scenario, `helm test`, `hack/smoke.sh`, routes through Traefik, an upgrade from the newest published chart, and a second upgrade that must keep credentials and pods; `Install result` sums up the scenarios |
| [Workflow lint](.github/workflows/actions-lint.yaml) | changes to workflows or `hack/*.sh` | actionlint, shellcheck and zizmor (`make lint-actions` locally) |
| [Renovate generate](.github/workflows/renovate-generate.yaml) | Renovate pull requests that change `values.yaml` or `Chart.yaml` | runs `make generate` and commits the result, see [below](#renovate-pull-requests) |
| [Nightly end-to-end](.github/workflows/e2e-nightly.yaml) | daily | `ci/full-values.yaml` (every optional component but embedding) with Functions built and executed in the cluster |
Expand Down Expand Up @@ -162,11 +162,12 @@ also opens a pull request for `appVersion`). To follow it:
`templates/workers/_workers.tpl` and by `workers.queues`), and new tasks.
4. Check whether the data migration changed (`src/Appwrite/Migration/Migration.php`)
and update [docs/upgrading.md](docs/upgrading.md) if it did.
5. Find what else names the old version, such as the docs, the chart icon
URL and the DNS check in the install workflow, with
`git grep -n <old version>`. Set `upgrade-from` in
[test-install.yaml](.github/workflows/test-install.yaml) to the version
the chart shipped until now.
5. Run `make check-versions`. It lists the docs, examples, values and the
chart icon URL that still name the old version. Recheck each claim against
the new version and update it, or write "Appwrite X.Y.Z and later" when
it's about the version that introduced something. The workflows need
nothing: they read `appVersion`, and the upgrade test starts from the
newest published chart.
6. Run `make generate test`, then test the upgrade on kind the way CI does:

```console
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ changes: ## Write the CHANGELOG.md section of the chart version into artifacthub
check-changes: ## Fail if artifacthub.io/changes doesn't match CHANGELOG.md (no-op until CHANGELOG.md has a section for the chart version)
hack/changelog-changes.sh --check

.PHONY: check-versions
check-versions: ## Fail if the docs, examples or workflows name an Appwrite version other than appVersion
hack/check-versions.sh

.PHONY: kubeconform
kubeconform: ## Validate rendered manifests against several Kubernetes versions
@for f in $(CHART)/ci/*-values.yaml; do \
Expand Down Expand Up @@ -115,7 +119,7 @@ template: ## Render the chart with default values
helm template $(RELEASE) $(CHART) -n $(NAMESPACE)

.PHONY: test
test: lint unittest kubeconform examples check-generated check-changes ## Run every static check
test: lint unittest kubeconform examples check-generated check-changes check-versions ## Run every static check

.PHONY: kind-up
kind-up: ## Create a local kind cluster
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ that enforces the `restricted` profile:
| Scenario | What it exercises |
| --- | --- |
| `default` | Built-in datastores and combined workers, on Kubernetes 1.29 and 1.37 |
| `default` | The data migration on upgrade, upgrade from Appwrite 2.2.0 |
| `default` | The chart upgrade and data migration, from the latest published chart |
| `hardened` | NetworkPolicies with restricted egress |
| `separate-workers`, `grouped-workers` | Worker topologies |
| `external-dbs` | PostgreSQL, Redis and ClickHouse outside the release |
Expand Down
2 changes: 1 addition & 1 deletion charts/appwrite/templates/_validate.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ configmap-env.yaml so it also runs under `helm template`.
{{- $errors = append $errors "compute.executor.existingSecret is required when compute.secrets.existingSecret or an S3 secretName (storage.s3.accessKeyId, storage.s3.secretAccessKey) is set: the executor runs in another namespace and can't read them. Create a Secret there with the keys executor-secret, s3-access-key and s3-secret-key." }}
{{- end }}
{{- if and (not $v.compute.secrets.existingSecret) (eq $v.compute.secrets.orchestratorSecret "your-secret-key") }}
{{- $errors = append $errors "compute.secrets.orchestratorSecret is Appwrite's public placeholder, which Appwrite 2.6.2 refuses for job callbacks, so every build would fail. Leave it empty for the chart to generate one, or set a random value." }}
{{- $errors = append $errors "compute.secrets.orchestratorSecret is Appwrite's public placeholder, which Appwrite 2.6.2 and later refuse for job callbacks, so every build would fail. Leave it empty for the chart to generate one, or set a random value." }}
{{- end }}
{{- if ne $storage.device "s3" }}
{{- $errors = append $errors "compute.enabled needs storage.device=s3: builds and the executor exchange code and build output through object storage. Keep the default (s3, with the built-in object store), or set compute.enabled=false to store files on the local volume without Functions and Sites." }}
Expand Down
4 changes: 2 additions & 2 deletions docs/integrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ appwrite:
Upgrade, then open a function or site in the console and choose *Connect
Git*. If GitHub shows a delivery error under the app's *Advanced* tab, check
that `https://<domain>/v1/vcs/github/events` is reachable from outside and
that the webhook secret matches. The secret is required: Appwrite 2.4.0 and
later refuse GitHub's events without `_APP_VCS_GITHUB_WEBHOOK_SECRET`.
that the webhook secret matches. The secret is required: Appwrite 2.4.0 and later
refuse GitHub's events without `_APP_VCS_GITHUB_WEBHOOK_SECRET`.

### GitLab, Gitea and Bitbucket

Expand Down
5 changes: 2 additions & 3 deletions docs/upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ The [changelog](../CHANGELOG.md) lists what changed in each chart version,
and [version notes](#version-notes) what you have to do about it.

What CI tests: a fresh install of the `appVersion`, and an upgrade from the
published chart 2.1.0 (Appwrite 2.6.1) with default values, including the
data migration.
latest published chart with default values, including the data migration.

## What happens during an upgrade

Expand Down Expand Up @@ -117,7 +116,7 @@ before upgrading.
running:

```text
Appwrite 2.3.0 is installed and this would downgrade it to 2.2.0. Appwrite can't migrate data backwards; restore a backup taken before the upgrade instead, or set migrations.allowDowngrade=true.
Appwrite <running version> is installed and this would downgrade it to <the chart's appVersion>. Appwrite can't migrate data backwards; restore a backup taken before the upgrade instead, or set migrations.allowDowngrade=true.
```

The check reads the running version with `lookup`, so it does nothing with
Expand Down
55 changes: 55 additions & 0 deletions hack/check-versions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# Fails when the docs, examples, values, templates or workflows name an
# Appwrite version other than appVersion in charts/appwrite/Chart.yaml, so an
# upgrade can't leave a claim about the old version behind.
#
# It looks at "Appwrite X.Y.Z", the appwrite/appwrite:X.Y.Z image and links
# into the appwrite/appwrite repository at a tag. History is allowed when it
# says so: "Appwrite 2.4.0 and later", "or later", or "Appwrite 2.4.0's ...".
# Not checked: CHANGELOG.md, the version notes in docs/upgrading.md,
# Chart.yaml's annotations, the unit tests (which use made-up versions) and
# generated files.
#
# Usage: hack/check-versions.sh
set -euo pipefail

CHART="${CHART:-charts/appwrite}"
app_version=$(awk '/^appVersion:/ {gsub(/"/, "", $2); print $2}' "$CHART/Chart.yaml")
[[ -n "$app_version" ]] || { echo "No appVersion in $CHART/Chart.yaml" >&2; exit 2; }

v='[0-9]+\.[0-9]+\.[0-9]+'
pattern="Appwrite ${v}('s| and later| or later)?|appwrite/appwrite:${v}|appwrite/appwrite/(blob/|tree/|raw/)?${v}/"

# Prints the line from which a file is history, if it has one: the version
# notes of docs/upgrading.md, and Chart.yaml's annotations (its changes are
# history, and hack/chart-images.sh checks its images).
history_from() {
case "$1" in
docs/upgrading.md) grep -n '^## Version notes' "$1" | cut -d: -f1 ;;
"$CHART/Chart.yaml") grep -n '^annotations:' "$1" | cut -d: -f1 ;;
esac
}

stale=0
while IFS= read -r file; do
history=$(history_from "$file" || true)
while IFS= read -r hit; do
line=${hit%%:*} match=${hit#*:}
case "$match" in *"'s" | *" and later" | *" or later") continue ;; esac
[[ -n "$history" && "$line" -ge "$history" ]] && continue
[[ "$match" =~ ($v) ]]
if [[ "${BASH_REMATCH[1]}" != "$app_version" ]]; then
echo "${file}:${line}: ${match} (the chart ships Appwrite ${app_version})"
stale=1
fi
done < <(grep -noE "$pattern" "$file" || true)
done < <(git ls-files README.md CONTRIBUTING.md RELEASING.md SECURITY.md 'docs/*.md' 'examples/*' \
"$CHART/Chart.yaml" "$CHART/README.md.gotmpl" "$CHART/values.yaml" "$CHART/templates/*" "$CHART/files/*" \
'.github/workflows/*' 'hack/*.sh')

if [[ "$stale" -ne 0 ]]; then
echo >&2
echo "Update these to Appwrite ${app_version}, or say which versions a claim covers (\"and later\")." >&2
exit 1
fi
echo "Every Appwrite version named matches appVersion ${app_version}."
Loading