From ced827dc998ceb9bafb70874093c9e1722283554 Mon Sep 17 00:00:00 2001 From: kayx23 Date: Thu, 13 Aug 2026 17:15:51 +0800 Subject: [PATCH 1/4] docs: add ADC CI/CD guidance --- docs/README.md | 1 + docs/guides/ci-cd.md | 219 ++++++++++++++++++++++++++++++++++++++++ docs/guides/workflow.md | 4 +- 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 docs/guides/ci-cd.md diff --git a/docs/README.md b/docs/README.md index 4be0650c..b8d21b5b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,6 +7,7 @@ Start with the workflow guide if you are setting up ADC for the first time. Use ## Get Started - [Use ADC for Declarative Configuration](./guides/workflow.md): configure a backend, write an `adc.yaml` file, lint it, preview changes, sync it, and export backups. +- [Manage Gateway Configuration in CI/CD](./guides/ci-cd.md): check pull requests, review deployment plans, protect credentials, detect drift, and roll back configuration. - [Resource IDs](./guides/resource-ids.md): understand how ADC matches local resources to remote resources, especially before adopting resources that were created outside ADC. - [Label Selector](./guides/label-selector.md): split ownership by labels so multiple teams or pipelines can manage one backend safely. diff --git a/docs/guides/ci-cd.md b/docs/guides/ci-cd.md new file mode 100644 index 00000000..a5941997 --- /dev/null +++ b/docs/guides/ci-cd.md @@ -0,0 +1,219 @@ +# Manage Gateway Configuration in CI/CD + +ADC can promote declarative Apache APISIX or API7 Enterprise configuration through a CI/CD pipeline. The pipeline checks proposed configuration, shows the expected gateway changes, waits for the required approval, and then reconciles the target gateway with the reviewed files. + +This is a push-based workflow: the CI/CD runner executes ADC and connects to the gateway Admin API. ADC configuration files are not Kubernetes resources, so a Kubernetes GitOps controller such as Argo CD or Flux does not apply them by itself. If you use a GitOps controller, run ADC in a separate CI job or in another explicitly designed execution mechanism. + +## Before You Begin + +- Install ADC on the CI/CD runner or use the published `api7/adc` container image. Pin a released version instead of using a floating tag. +- Store the declarative configuration in version control. See [Use ADC for Declarative Configuration](./workflow.md) to create or adopt an `adc.yaml` file. +- Ensure that the runner can reach the target Admin API. +- Create a separate credential for the pipeline. Grant it only the permissions required for its target gateway group or environment when the backend supports scoped credentials. +- Decide which resources each pipeline owns before its first deployment. + +The examples use ADC `0.29.0` and a file at `gateway/adc.yaml`. Change the version and path to match your repository. + +> **Apache APISIX backend:** The ADC Apache APISIX backend is experimental. Although current APISIX releases are tested, some APISIX resources or equivalent configuration forms do not round-trip to an identical representation and can produce a persistent diff. Validate the exact resource types and APISIX version used by your pipeline before adopting automatic production synchronization. See [Apache APISIX backend notes](../../libs/backend-apisix/README.md). + +## Define an Ownership Scope + +`adc sync` can create, update, and delete resources in its command scope. A remote resource that is in scope but absent from the local files can be deleted. Do not let independent pipelines reconcile the same unpartitioned backend. + +Use a label selector to give one application or team an independent ownership scope: + +```shell +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production +``` + +ADC injects the selector labels into the local resources and compares them only with remote resources carrying the same labels. Use the same selector for `validate`, `diff`, `sync`, and scheduled drift checks. + +For API7 Enterprise, also select the target gateway group with `ADC_GATEWAY_GROUP` or `--gateway-group`. A gateway group separates runtime targets, while a label selector can divide ownership within that group. + +> **Note:** ADC adds the `managed-by=adc` label to supported local resources by default, but that label alone does not limit the command scope. Use an explicit `--label-selector` whenever a backend or gateway group contains resources owned by another team or tool. + +Label selectors operate on top-level resources. They cannot divide ownership of routes nested in the same service, and they do not scope `global_rules` or `plugin_metadata`. See [Label Selector](./label-selector.md) before sharing a backend between pipelines. + +## Store Connection Settings Securely + +Configure backend connection settings as protected CI/CD secrets instead of committing a `.env` file: + +| Setting | Apache APISIX | API7 Enterprise | +| ------------------- | ------------- | ----------------------------- | +| `ADC_BACKEND` | `apisix` | `api7ee` | +| `ADC_SERVER` | Admin API URL | API7 Enterprise Admin API URL | +| `ADC_TOKEN` | Admin API key | Dashboard API token | +| `ADC_GATEWAY_GROUP` | Not used | Target gateway group | + +Use a trusted CA certificate with `ADC_CA_CERT_FILE` when the endpoint uses a private certificate authority. Store a client certificate and key in protected secrets if the endpoint requires mutual TLS. Do not use `ADC_TLS_SKIP_VERIFY` in a production pipeline. + +Do not expose write-capable credentials to workflows triggered from untrusted forks. Run local lint checks without secrets for all pull requests, and restrict backend validation, planning, and deployment jobs to trusted code and protected environments. + +## Check Pull Requests + +Run `lint` for every proposed change. It verifies ADC syntax and schema rules without connecting to a backend: + +```shell +adc lint -f gateway/adc.yaml +``` + +For trusted pull requests, also validate against a non-production backend and produce a diff: + +```shell +adc validate \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=staging + +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=staging +``` + +`validate` catches backend-specific errors without applying the proposed changes. `diff` prints a summary and writes the complete machine-readable plan to `diff.yaml`. Upload `diff.yaml` as a CI artifact so reviewers can inspect creates, updates, and deletions. + +`adc diff` exits successfully when it finds differences. If a policy requires the job to fail on drift, inspect `diff.yaml` explicitly as shown in [Detect Drift](#detect-drift). + +## Plan and Deploy a Change + +Keep planning and deployment as separate jobs. The plan job validates the files and publishes `diff.yaml`. The deployment job should require the appropriate environment approval, recalculate the diff against the latest backend state, and then synchronize the reviewed configuration. + +Use the same version, files, backend, gateway group, resource filters, and label selector in both jobs. If any of these inputs differ, the approved plan does not describe the deployment scope. + +### Plan + +```shell +adc validate \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production + +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production +``` + +Review `diff.yaml`, paying particular attention to `delete` events. A large or unexpected deletion usually means that a file, selector, gateway group, or resource filter does not match the intended ownership scope. + +### Deploy + +After approval, recalculate the plan and apply the desired state: + +```shell +adc validate \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production + +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production + +adc sync \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production +``` + +Serialize deployments that target the same ownership scope. For example, a GitHub Actions deployment workflow can use: + +```yaml +concurrency: + group: adc-production-catalog + cancel-in-progress: false +``` + +Do not cancel a deployment after `adc sync` has started. ADC sends resource operations through the Admin API and does not apply the entire plan as one atomic transaction. If a runner or request fails partway through, preserve the logs, correct the failure, and run the same desired configuration again to converge the backend. + +Use `--request-concurrent` to reduce request concurrency when the Admin API is rate limited. It changes request parallelism, not the ownership or deletion scope. + +## Run ADC from a Container + +The ADC image is published to Docker Hub and GitHub Container Registry for `linux/amd64` and `linux/arm64`. The following helper runs a pinned image and mounts the repository at `/work`: + +```shell +ADC_IMAGE=api7/adc:0.29.0 + +docker run --rm \ + -v "${PWD}:/work" \ + -w /work \ + --entrypoint /nodejs/bin/node \ + -e ADC_BACKEND \ + -e ADC_SERVER \ + -e ADC_TOKEN \ + -e ADC_GATEWAY_GROUP \ + "$ADC_IMAGE" \ + /home/nonroot/main.cjs lint -f gateway/adc.yaml +``` + +The explicit entrypoint keeps the repository as the working directory while running the image's ADC executable at `/home/nonroot/main.cjs`. Add the same `docker run` options for `validate`, `diff`, and `sync`. Mount CA and mutual TLS files read-only when those files are not already in the repository: + +```shell +-v "${RUNNER_TEMP}/gateway-ca.pem:/certs/gateway-ca.pem:ro" \ +-e ADC_CA_CERT_FILE=/certs/gateway-ca.pem +``` + +For stronger supply-chain reproducibility, pin the image digest recorded by your artifact policy in addition to the release version. + +## Verify a Deployment + +Run the same diff immediately after synchronization: + +```shell +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production +``` + +For configuration that round-trips without backend normalization, `diff.yaml` should contain an empty list: + +```yaml +[] +``` + +If the same diff remains after a successful sync, inspect whether the backend populated defaults or normalized an equivalent configuration form. Align the source file with a stable ADC representation when possible, and test the result again. Do not suppress every repeated event: it could also indicate a failed operation or real drift. + +Then run application-level smoke tests through the gateway. ADC verifies and reconciles gateway configuration, but it does not prove that upstream applications, DNS, certificates, or external dependencies behave as expected. + +## Detect Drift + +After confirming that the desired configuration produces a stable empty diff, run a scheduled `diff` with the same target and ownership settings as the deployment job. The following check fails when `diff.yaml` contains one or more events: + +```shell +adc diff \ + -f gateway/adc.yaml \ + --label-selector team=catalog,env=production + +if [ "$(tr -d '[:space:]' < diff.yaml)" != "[]" ]; then + echo "Gateway configuration drift detected. Review diff.yaml." + exit 1 +fi +``` + +Upload `diff.yaml` even when the job fails. Investigate whether the difference came from an intentional emergency change, another automation system, an incorrect ownership scope, or a failed deployment. Do not automatically overwrite unexplained production drift before reviewing it. + +## Roll Back + +Gateway configuration should be rolled back from the same version-controlled source of truth: + +1. Revert the configuration commit or select a previously approved revision. +2. Run `lint`, `validate`, and `diff` against the target backend. +3. Review the rollback plan for destructive changes. +4. Run `sync` with the same ownership scope used for deployment. +5. Confirm that `diff.yaml` is empty and repeat the application smoke tests. + +Keep exported backups when you adopt existing resources or when your operational policy requires an independent recovery artifact: + +```shell +adc dump \ + --with-id \ + --label-selector team=catalog,env=production \ + -o gateway-backup.yaml +``` + +Treat a dump as sensitive configuration. Store it in an access-controlled artifact location and define a retention policy. + +## Related + +- [Use ADC for Declarative Configuration](./workflow.md) +- [Resource IDs](./resource-ids.md) +- [Label Selector](./label-selector.md) +- [CLI Command Reference](../reference/cli.md) diff --git a/docs/guides/workflow.md b/docs/guides/workflow.md index 80a88853..65603ea5 100644 --- a/docs/guides/workflow.md +++ b/docs/guides/workflow.md @@ -86,7 +86,6 @@ An ADC file can define services, routes, consumers, global rules, plugin metadat services: - name: httpbin-service upstream: - name: default scheme: http type: roundrobin nodes: @@ -184,9 +183,12 @@ adc sync -f adc.yaml Run `sync` only after the diff has been reviewed or approved by your release process. +See [Manage Gateway Configuration in CI/CD](./ci-cd.md) for production guidance on ownership scopes, protected credentials, plan artifacts, deployment approvals, drift detection, verification, and rollback. + ## Related - [CLI Command Reference](../reference/cli.md) - [Configuration Reference](../reference/configuration.md) - [Resource IDs](./resource-ids.md) - [Label Selector](./label-selector.md) +- [Manage Gateway Configuration in CI/CD](./ci-cd.md) From 3bf7db1c9ba164d93006fa3a0cd6ddf071295641 Mon Sep 17 00:00:00 2001 From: kayx23 Date: Thu, 13 Aug 2026 17:34:28 +0800 Subject: [PATCH 2/4] docs: clarify ADC CI/CD workflow --- docs/guides/ci-cd.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/guides/ci-cd.md b/docs/guides/ci-cd.md index a5941997..11c10e01 100644 --- a/docs/guides/ci-cd.md +++ b/docs/guides/ci-cd.md @@ -1,10 +1,10 @@ # Manage Gateway Configuration in CI/CD -ADC can promote declarative Apache APISIX or API7 Enterprise configuration through a CI/CD pipeline. The pipeline checks proposed configuration, shows the expected gateway changes, waits for the required approval, and then reconciles the target gateway with the reviewed files. +Use ADC in a CI/CD pipeline to validate and deploy declarative Apache APISIX or API7 Enterprise configuration. The pipeline checks proposed configuration, shows the expected gateway changes, waits for the required approval, and then reconciles the target gateway with the reviewed files. -This is a push-based workflow: the CI/CD runner executes ADC and connects to the gateway Admin API. ADC configuration files are not Kubernetes resources, so a Kubernetes GitOps controller such as Argo CD or Flux does not apply them by itself. If you use a GitOps controller, run ADC in a separate CI job or in another explicitly designed execution mechanism. +The CI/CD runner deploys the configuration by running ADC and connecting to the gateway Admin API. Unlike Argo CD or Flux, ADC does not continuously watch a Git repository for changes. ADC configuration files are not Kubernetes resources, so run ADC in a separate CI job when you also use a Kubernetes GitOps controller. -## Before You Begin +## Prerequisites - Install ADC on the CI/CD runner or use the published `api7/adc` container image. Pin a released version instead of using a floating tag. - Store the declarative configuration in version control. See [Use ADC for Declarative Configuration](./workflow.md) to create or adopt an `adc.yaml` file. @@ -22,7 +22,7 @@ The examples use ADC `0.29.0` and a file at `gateway/adc.yaml`. Change the versi Use a label selector to give one application or team an independent ownership scope: -```shell +```bash adc diff \ -f gateway/adc.yaml \ --label-selector team=catalog,env=production @@ -55,13 +55,13 @@ Do not expose write-capable credentials to workflows triggered from untrusted fo Run `lint` for every proposed change. It verifies ADC syntax and schema rules without connecting to a backend: -```shell +```bash adc lint -f gateway/adc.yaml ``` For trusted pull requests, also validate against a non-production backend and produce a diff: -```shell +```bash adc validate \ -f gateway/adc.yaml \ --label-selector team=catalog,env=staging @@ -83,7 +83,7 @@ Use the same version, files, backend, gateway group, resource filters, and label ### Plan -```shell +```bash adc validate \ -f gateway/adc.yaml \ --label-selector team=catalog,env=production @@ -99,7 +99,7 @@ Review `diff.yaml`, paying particular attention to `delete` events. A large or u After approval, recalculate the plan and apply the desired state: -```shell +```bash adc validate \ -f gateway/adc.yaml \ --label-selector team=catalog,env=production @@ -129,7 +129,7 @@ Use `--request-concurrent` to reduce request concurrency when the Admin API is r The ADC image is published to Docker Hub and GitHub Container Registry for `linux/amd64` and `linux/arm64`. The following helper runs a pinned image and mounts the repository at `/work`: -```shell +```bash ADC_IMAGE=api7/adc:0.29.0 docker run --rm \ @@ -146,7 +146,7 @@ docker run --rm \ The explicit entrypoint keeps the repository as the working directory while running the image's ADC executable at `/home/nonroot/main.cjs`. Add the same `docker run` options for `validate`, `diff`, and `sync`. Mount CA and mutual TLS files read-only when those files are not already in the repository: -```shell +```bash -v "${RUNNER_TEMP}/gateway-ca.pem:/certs/gateway-ca.pem:ro" \ -e ADC_CA_CERT_FILE=/certs/gateway-ca.pem ``` @@ -157,7 +157,7 @@ For stronger supply-chain reproducibility, pin the image digest recorded by your Run the same diff immediately after synchronization: -```shell +```bash adc diff \ -f gateway/adc.yaml \ --label-selector team=catalog,env=production @@ -177,7 +177,7 @@ Then run application-level smoke tests through the gateway. ADC verifies and rec After confirming that the desired configuration produces a stable empty diff, run a scheduled `diff` with the same target and ownership settings as the deployment job. The following check fails when `diff.yaml` contains one or more events: -```shell +```bash adc diff \ -f gateway/adc.yaml \ --label-selector team=catalog,env=production @@ -202,7 +202,7 @@ Gateway configuration should be rolled back from the same version-controlled sou Keep exported backups when you adopt existing resources or when your operational policy requires an independent recovery artifact: -```shell +```bash adc dump \ --with-id \ --label-selector team=catalog,env=production \ From 18eb145d45d90dd27a96974f3d63c4374513e08d Mon Sep 17 00:00:00 2001 From: kayx23 Date: Wed, 26 Aug 2026 14:29:09 +0800 Subject: [PATCH 3/4] docs: correct ADC CI/CD operational limits The previous CI example treated validate, empty diffs, and container `--user` as always safe. Local ADC 0.29.0 runs against APISIX 3.13 showed those assumptions fail, so the guide now matches actual command and image behavior before review. --- docs/README.md | 2 +- docs/guides/ci-cd.md | 108 +++++++++++++++++++++++----------------- docs/guides/workflow.md | 13 +---- 3 files changed, 65 insertions(+), 58 deletions(-) diff --git a/docs/README.md b/docs/README.md index b8d21b5b..eba489cc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,9 +7,9 @@ Start with the workflow guide if you are setting up ADC for the first time. Use ## Get Started - [Use ADC for Declarative Configuration](./guides/workflow.md): configure a backend, write an `adc.yaml` file, lint it, preview changes, sync it, and export backups. -- [Manage Gateway Configuration in CI/CD](./guides/ci-cd.md): check pull requests, review deployment plans, protect credentials, detect drift, and roll back configuration. - [Resource IDs](./guides/resource-ids.md): understand how ADC matches local resources to remote resources, especially before adopting resources that were created outside ADC. - [Label Selector](./guides/label-selector.md): split ownership by labels so multiple teams or pipelines can manage one backend safely. +- [Manage Gateway Configuration in CI/CD](./guides/ci-cd.md): check pull requests, review deployment plans, protect credentials, detect drift, and roll back configuration. ## Reference diff --git a/docs/guides/ci-cd.md b/docs/guides/ci-cd.md index 11c10e01..8763e78f 100644 --- a/docs/guides/ci-cd.md +++ b/docs/guides/ci-cd.md @@ -2,20 +2,52 @@ Use ADC in a CI/CD pipeline to validate and deploy declarative Apache APISIX or API7 Enterprise configuration. The pipeline checks proposed configuration, shows the expected gateway changes, waits for the required approval, and then reconciles the target gateway with the reviewed files. -The CI/CD runner deploys the configuration by running ADC and connecting to the gateway Admin API. Unlike Argo CD or Flux, ADC does not continuously watch a Git repository for changes. ADC configuration files are not Kubernetes resources, so run ADC in a separate CI job when you also use a Kubernetes GitOps controller. +The CI/CD runner deploys configuration by running ADC and calling the gateway Admin API. ADC does not watch a Git repository and `adc.yaml` is not a Kubernetes resource, so Argo CD and Flux cannot apply it. If you also use a Kubernetes GitOps controller, run ADC in a separate CI job. ## Prerequisites -- Install ADC on the CI/CD runner or use the published `api7/adc` container image. Pin a released version instead of using a floating tag. +- Install ADC on the CI/CD runner or use the published `api7/adc` container image. Pin a released version instead of `latest` or `dev`. - Store the declarative configuration in version control. See [Use ADC for Declarative Configuration](./workflow.md) to create or adopt an `adc.yaml` file. - Ensure that the runner can reach the target Admin API. -- Create a separate credential for the pipeline. Grant it only the permissions required for its target gateway group or environment when the backend supports scoped credentials. -- Decide which resources each pipeline owns before its first deployment. +- Create a dedicated credential for the pipeline. Restrict it to the target gateway group or environment when the backend can scope that identity. +- Decide which resources each pipeline owns before its first deployment. See [Label Selector](./label-selector.md) if more than one team or tool shares a backend. The examples use ADC `0.29.0` and a file at `gateway/adc.yaml`. Change the version and path to match your repository. > **Apache APISIX backend:** The ADC Apache APISIX backend is experimental. Although current APISIX releases are tested, some APISIX resources or equivalent configuration forms do not round-trip to an identical representation and can produce a persistent diff. Validate the exact resource types and APISIX version used by your pipeline before adopting automatic production synchronization. See [Apache APISIX backend notes](../../libs/backend-apisix/README.md). +## Run ADC in CI + +Install a pinned ADC release on the runner, or run the published image. The image is available from Docker Hub (`api7/adc`) and GitHub Container Registry (`ghcr.io/api7/adc`) for `linux/amd64` and `linux/arm64`. + +ADC writes `diff.yaml` into the current working directory, so mount the repository and set the container workdir to that mount. The image entrypoint looks up `main.cjs` relative to the workdir, so override the entrypoint and call `/home/nonroot/main.cjs`. + +The image runs as uid `65532`. Do not run it as the host user: `/home/nonroot` is not world-readable, so the binary would be unreachable. Make the mounted directory writable by uid `65532` so ADC can create `diff.yaml` (for example, `chmod a+w .` on a GitHub Actions checkout): + +```bash +ADC_IMAGE=api7/adc:0.29.0 + +docker run --rm \ + -v "${PWD}:/work" \ + -w /work \ + --entrypoint /nodejs/bin/node \ + -e ADC_BACKEND \ + -e ADC_SERVER \ + -e ADC_TOKEN \ + -e ADC_GATEWAY_GROUP \ + "$ADC_IMAGE" \ + /home/nonroot/main.cjs lint -f gateway/adc.yaml +``` + +Reuse the same `docker run` options for `validate`, `diff`, `sync`, and `dump`. Mount CA and mutual TLS files read-only when those files are not already in the repository: + +```bash +-v "/path/to/gateway-ca.pem:/certs/gateway-ca.pem:ro" \ +-e ADC_CA_CERT_FILE=/certs/gateway-ca.pem +``` + +For stronger supply-chain reproducibility, pin the image digest recorded by your artifact policy in addition to the release version. + ## Define an Ownership Scope `adc sync` can create, update, and delete resources in its command scope. A remote resource that is in scope but absent from the local files can be deleted. Do not let independent pipelines reconcile the same unpartitioned backend. @@ -30,9 +62,9 @@ adc diff \ ADC injects the selector labels into the local resources and compares them only with remote resources carrying the same labels. Use the same selector for `validate`, `diff`, `sync`, and scheduled drift checks. -For API7 Enterprise, also select the target gateway group with `ADC_GATEWAY_GROUP` or `--gateway-group`. A gateway group separates runtime targets, while a label selector can divide ownership within that group. +For API7 Enterprise, also set the target gateway group with `ADC_GATEWAY_GROUP` or `--gateway-group`. If you omit it, ADC uses `default`. A gateway group selects the runtime target; a label selector can divide ownership within that group. -> **Note:** ADC adds the `managed-by=adc` label to supported local resources by default, but that label alone does not limit the command scope. Use an explicit `--label-selector` whenever a backend or gateway group contains resources owned by another team or tool. +> **Note:** ADC adds the `managed-by=adc` label to supported local resources by default, but that label is not used as a default selector. Without `--label-selector`, `adc sync` still reconciles every resource in the command scope, including resources created outside ADC. Use an explicit selector whenever a backend or gateway group contains resources owned by another team or tool. Label selectors operate on top-level resources. They cannot divide ownership of routes nested in the same service, and they do not scope `global_rules` or `plugin_metadata`. See [Label Selector](./label-selector.md) before sharing a backend between pipelines. @@ -47,9 +79,9 @@ Configure backend connection settings as protected CI/CD secrets instead of comm | `ADC_TOKEN` | Admin API key | Dashboard API token | | `ADC_GATEWAY_GROUP` | Not used | Target gateway group | -Use a trusted CA certificate with `ADC_CA_CERT_FILE` when the endpoint uses a private certificate authority. Store a client certificate and key in protected secrets if the endpoint requires mutual TLS. Do not use `ADC_TLS_SKIP_VERIFY` in a production pipeline. +Use a trusted CA certificate with `ADC_CA_CERT_FILE` when the endpoint uses a private certificate authority. Store a client certificate and key in `ADC_TLS_CLIENT_CERT_FILE` and `ADC_TLS_CLIENT_KEY_FILE` if the endpoint requires mutual TLS. Do not use `ADC_TLS_SKIP_VERIFY` in a production pipeline. -Do not expose write-capable credentials to workflows triggered from untrusted forks. Run local lint checks without secrets for all pull requests, and restrict backend validation, planning, and deployment jobs to trusted code and protected environments. +Do not expose write-capable credentials to workflows triggered from untrusted forks. Run local lint checks without secrets for every pull request, and restrict backend validation, planning, and deployment jobs to trusted code and protected environments. ## Check Pull Requests @@ -59,7 +91,7 @@ Run `lint` for every proposed change. It verifies ADC syntax and schema rules wi adc lint -f gateway/adc.yaml ``` -For trusted pull requests, also validate against a non-production backend and produce a diff: +For trusted pull requests, also produce a diff against a non-production backend. Run `validate` first when the backend supports it: ```bash adc validate \ @@ -71,18 +103,20 @@ adc diff \ --label-selector team=catalog,env=staging ``` -`validate` catches backend-specific errors without applying the proposed changes. `diff` prints a summary and writes the complete machine-readable plan to `diff.yaml`. Upload `diff.yaml` as a CI artifact so reviewers can inspect creates, updates, and deletions. +`validate` asks the backend to check the proposed resources without applying them. It requires API7 Enterprise 3.9.10 or later. On Apache APISIX, ADC calls `/apisix/admin/configs/validate`; if that endpoint is missing, the command fails and you should skip `validate` on that version. `diff` prints a summary and writes the complete machine-readable plan to `diff.yaml`. Upload `diff.yaml` as a CI artifact so reviewers can inspect creates, updates, and deletions. -`adc diff` exits successfully when it finds differences. If a policy requires the job to fail on drift, inspect `diff.yaml` explicitly as shown in [Detect Drift](#detect-drift). +ADC has no apply-plan command. Reviewers inspect `diff.yaml`; they do not apply that file. `adc diff` also exits successfully when it finds differences. If a policy requires the job to fail on drift, inspect `diff.yaml` explicitly as shown in [Detect Drift](#detect-drift). ## Plan and Deploy a Change -Keep planning and deployment as separate jobs. The plan job validates the files and publishes `diff.yaml`. The deployment job should require the appropriate environment approval, recalculate the diff against the latest backend state, and then synchronize the reviewed configuration. +Keep planning and deployment as separate jobs. The plan job publishes `diff.yaml`. Include `validate` in that job when the backend supports it. The deployment job should require environment approval, recalculate the diff against the latest backend state, and then synchronize the reviewed configuration. -Use the same version, files, backend, gateway group, resource filters, and label selector in both jobs. If any of these inputs differ, the approved plan does not describe the deployment scope. +Use the same ADC version, files, backend, gateway group, resource filters, and label selector in both jobs. If any of these inputs differ, the approved plan does not describe the deployment scope. ### Plan +Omit `validate` when the backend does not implement it. + ```bash adc validate \ -f gateway/adc.yaml \ @@ -97,7 +131,7 @@ Review `diff.yaml`, paying particular attention to `delete` events. A large or u ### Deploy -After approval, recalculate the plan and apply the desired state: +After approval, recalculate the plan from the reviewed files. Compare that live plan with the approved artifact, or re-review it, before `sync`. If the live plan contains unexpected operations, stop and run the plan job again instead of synchronizing a different change set: ```bash adc validate \ @@ -121,38 +155,10 @@ concurrency: cancel-in-progress: false ``` -Do not cancel a deployment after `adc sync` has started. ADC sends resource operations through the Admin API and does not apply the entire plan as one atomic transaction. If a runner or request fails partway through, preserve the logs, correct the failure, and run the same desired configuration again to converge the backend. +Do not cancel a deployment after `adc sync` has started. ADC sends resource operations through the Admin API and does not apply the entire plan as one atomic transaction. Concurrent requests can succeed before a later request fails. If a runner or request fails partway through, preserve the logs, correct the failure, and run the same desired configuration again to converge the backend. Use `--request-concurrent` to reduce request concurrency when the Admin API is rate limited. It changes request parallelism, not the ownership or deletion scope. -## Run ADC from a Container - -The ADC image is published to Docker Hub and GitHub Container Registry for `linux/amd64` and `linux/arm64`. The following helper runs a pinned image and mounts the repository at `/work`: - -```bash -ADC_IMAGE=api7/adc:0.29.0 - -docker run --rm \ - -v "${PWD}:/work" \ - -w /work \ - --entrypoint /nodejs/bin/node \ - -e ADC_BACKEND \ - -e ADC_SERVER \ - -e ADC_TOKEN \ - -e ADC_GATEWAY_GROUP \ - "$ADC_IMAGE" \ - /home/nonroot/main.cjs lint -f gateway/adc.yaml -``` - -The explicit entrypoint keeps the repository as the working directory while running the image's ADC executable at `/home/nonroot/main.cjs`. Add the same `docker run` options for `validate`, `diff`, and `sync`. Mount CA and mutual TLS files read-only when those files are not already in the repository: - -```bash --v "${RUNNER_TEMP}/gateway-ca.pem:/certs/gateway-ca.pem:ro" \ --e ADC_CA_CERT_FILE=/certs/gateway-ca.pem -``` - -For stronger supply-chain reproducibility, pin the image digest recorded by your artifact policy in addition to the release version. - ## Verify a Deployment Run the same diff immediately after synchronization: @@ -169,7 +175,7 @@ For configuration that round-trips without backend normalization, `diff.yaml` sh [] ``` -If the same diff remains after a successful sync, inspect whether the backend populated defaults or normalized an equivalent configuration form. Align the source file with a stable ADC representation when possible, and test the result again. Do not suppress every repeated event: it could also indicate a failed operation or real drift. +If the same diff remains after a successful sync, inspect whether the backend populated defaults or normalized an equivalent configuration form. Align the source file with a stable ADC representation when possible, and test the result again. Do not enable a failing drift job, and do not suppress repeated events blindly: a persistent diff can also indicate a failed operation or real drift. Apache APISIX often fills defaults such as route `priority` and upstream `hash_on`; see [Apache APISIX backend notes](../../libs/backend-apisix/README.md). Then run application-level smoke tests through the gateway. ADC verifies and reconciles gateway configuration, but it does not prove that upstream applications, DNS, certificates, or external dependencies behave as expected. @@ -195,7 +201,7 @@ Upload `diff.yaml` even when the job fails. Investigate whether the difference c Gateway configuration should be rolled back from the same version-controlled source of truth: 1. Revert the configuration commit or select a previously approved revision. -2. Run `lint`, `validate`, and `diff` against the target backend. +2. Run `lint` and `diff` against the target backend. Run `validate` when the backend supports it. 3. Review the rollback plan for destructive changes. 4. Run `sync` with the same ownership scope used for deployment. 5. Confirm that `diff.yaml` is empty and repeat the application smoke tests. @@ -209,7 +215,17 @@ adc dump \ -o gateway-backup.yaml ``` -Treat a dump as sensitive configuration. Store it in an access-controlled artifact location and define a retention policy. +Treat a dump as sensitive configuration. Store it in an access-controlled artifact location and define a retention policy. Dumped files can include empty `global_rules` and `plugin_metadata` maps. Those resources are not limited by `--label-selector`, so do not sync a dump back until you have removed keys you do not own. + +## Map the Model onto Your CI System + +Provider YAML differs, but the job boundaries should not: + +- Every pull request: `lint` only, with no Admin API credentials. +- Trusted code only: `diff` against a non-production backend (and `validate` when supported), then upload `diff.yaml`. +- Protected production environment: recalculate the plan, review unexpected operations, then `sync`. +- One concurrency group per ownership scope for jobs that can call `sync`. Do not cancel an in-progress sync when a newer job is queued. +- Scheduled drift detection: `diff` only. Do not grant that job permission to `sync`. ## Related diff --git a/docs/guides/workflow.md b/docs/guides/workflow.md index 65603ea5..18016b61 100644 --- a/docs/guides/workflow.md +++ b/docs/guides/workflow.md @@ -130,7 +130,7 @@ Run `adc validate` when you want backend-side validation without applying change adc validate -f adc.yaml ``` -`validate` asks the backend to validate the resources described by the local file. This is useful in CI because it catches issues that only the target backend can know, such as unsupported plugin configuration. +`validate` asks the backend to validate the resources described by the local file. This is useful in CI because it catches issues that only the target backend can know, such as unsupported plugin configuration. Skip it when the backend version does not implement configuration validation; see [Manage Gateway Configuration in CI/CD](./ci-cd.md). ## Preview Changes @@ -172,16 +172,7 @@ Plain OpenAPI documents describe APIs, not gateway-specific behavior. Add `x-adc ## Suggested CI Flow -For a pull request or deployment pipeline, use this order: - -```bash -adc lint -f adc.yaml -adc validate -f adc.yaml -adc diff -f adc.yaml -adc sync -f adc.yaml -``` - -Run `sync` only after the diff has been reviewed or approved by your release process. +`lint`, `validate`, `diff`, and `sync` are the building blocks, but they are not a complete production pipeline on their own. Lint every pull request without credentials. After review, plan against the target backend (`validate` when the backend supports it, then `diff`), then sync only from an approved job that uses the same ownership scope. See [Manage Gateway Configuration in CI/CD](./ci-cd.md) for production guidance on ownership scopes, protected credentials, plan artifacts, deployment approvals, drift detection, verification, and rollback. From cdbf3ce9d99991fc4c1f8d70fd42b3f5b12ac7e7 Mon Sep 17 00:00:00 2001 From: kayx23 Date: Wed, 26 Aug 2026 14:39:21 +0800 Subject: [PATCH 4/4] docs: pin APISIX validate support to 3.17+ ADC's own e2e suite gates validate at 3.17.0. Rechecking 3.18.0 showed validate succeeding and a minimal service round-tripping to an empty diff, so the CI guide should not treat 3.13 Admin API gaps as current APISIX behavior. --- docs/guides/ci-cd.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guides/ci-cd.md b/docs/guides/ci-cd.md index 8763e78f..1ff895ff 100644 --- a/docs/guides/ci-cd.md +++ b/docs/guides/ci-cd.md @@ -103,7 +103,7 @@ adc diff \ --label-selector team=catalog,env=staging ``` -`validate` asks the backend to check the proposed resources without applying them. It requires API7 Enterprise 3.9.10 or later. On Apache APISIX, ADC calls `/apisix/admin/configs/validate`; if that endpoint is missing, the command fails and you should skip `validate` on that version. `diff` prints a summary and writes the complete machine-readable plan to `diff.yaml`. Upload `diff.yaml` as a CI artifact so reviewers can inspect creates, updates, and deletions. +`validate` asks the backend to check the proposed resources without applying them. It requires API7 Enterprise 3.9.10 or later, or Apache APISIX 3.17 or later. On older APISIX versions the Admin API has no `/apisix/admin/configs/validate` endpoint and the command fails; skip `validate` then. `diff` prints a summary and writes the complete machine-readable plan to `diff.yaml`. Upload `diff.yaml` as a CI artifact so reviewers can inspect creates, updates, and deletions. ADC has no apply-plan command. Reviewers inspect `diff.yaml`; they do not apply that file. `adc diff` also exits successfully when it finds differences. If a policy requires the job to fail on drift, inspect `diff.yaml` explicitly as shown in [Detect Drift](#detect-drift). @@ -175,7 +175,7 @@ For configuration that round-trips without backend normalization, `diff.yaml` sh [] ``` -If the same diff remains after a successful sync, inspect whether the backend populated defaults or normalized an equivalent configuration form. Align the source file with a stable ADC representation when possible, and test the result again. Do not enable a failing drift job, and do not suppress repeated events blindly: a persistent diff can also indicate a failed operation or real drift. Apache APISIX often fills defaults such as route `priority` and upstream `hash_on`; see [Apache APISIX backend notes](../../libs/backend-apisix/README.md). +If the same diff remains after a successful sync, inspect whether the backend populated defaults or normalized an equivalent configuration form. Align the source file with a stable ADC representation when possible, and test the result again. Do not enable a failing drift job, and do not suppress repeated events blindly: a persistent diff can also indicate a failed operation or real drift. Some Apache APISIX versions fill defaults such as route `priority` and upstream `hash_on`; see [Apache APISIX backend notes](../../libs/backend-apisix/README.md). Test the exact APISIX version your pipeline uses before treating an empty `diff.yaml` as the expected post-sync result. Then run application-level smoke tests through the gateway. ADC verifies and reconciles gateway configuration, but it does not prove that upstream applications, DNS, certificates, or external dependencies behave as expected.