Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
831656b
chore: run DELETE to clean up the bucket
kptdobe Dec 4, 2025
b60b724
chore: extract it tests
kptdobe Dec 4, 2025
9fd0cd4
chore: sequential tests
kptdobe Dec 4, 2025
fc96415
Merge branch 'main' into cleanup
kptdobe Dec 8, 2025
0aa1d3f
Merge branch 'main' into cleanup
kptdobe Dec 8, 2025
fa8bb0d
chore: linting
kptdobe Dec 8, 2025
a5f9784
chore: postdeploy tests
kptdobe Dec 8, 2025
629b6c7
chore: posix compliant source
kptdobe Dec 8, 2025
65bf3b3
chore: multi env comp
kptdobe Dec 8, 2025
22c2af4
chore: use anonymous
kptdobe Dec 8, 2025
6ec19b6
chore: let's break it!
kptdobe Dec 8, 2025
ceeb6a5
Revert "chore: let's break it!"
kptdobe Dec 8, 2025
5dec3b6
GH-221 - Disable anonymous access
auniverseaway Dec 12, 2025
baeaab8
Change to 401 for anonymous users
auniverseaway Dec 12, 2025
7e19abf
Merge branch 'main' into postdeploy
kptdobe Dec 16, 2025
e3bd95a
Merge remote-tracking branch 'origin/noanon' into postdeploy
kptdobe Dec 16, 2025
033682e
chore: rename
kptdobe Dec 16, 2025
4c7a6bd
chore: ims cleanup
kptdobe Dec 16, 2025
b4a2c81
chore: prepare for ims stage
kptdobe Dec 16, 2025
974d491
chore: IMS integration
kptdobe Dec 17, 2025
99afbdd
chore: dep
kptdobe Dec 17, 2025
5cce911
chore: secrets
kptdobe Dec 17, 2025
352c5bd
chore: wrong task
kptdobe Dec 17, 2025
9f5ff0e
chore: move branch name inside repo name
kptdobe Dec 17, 2025
0c77878
chore: relax test
kptdobe Dec 17, 2025
ddb8538
chore: allow copy/paste
kptdobe Dec 17, 2025
4313575
chore: create folder is more simple
kptdobe Dec 17, 2025
94aa0f2
chore: final cleanup
kptdobe Dec 17, 2025
5cb8159
chore: doc
kptdobe Dec 17, 2025
a7eb2e0
Merge branch 'main' into postdeploy
kptdobe Dec 18, 2025
d328048
chore: doc + rename
kptdobe Dec 22, 2025
1690876
chore: more doc
kptdobe Dec 22, 2025
3ba3e3f
chore: doc
kptdobe Dec 22, 2025
624a3bc
chore: multiple users tests
kptdobe Dec 22, 2025
ddbb8a5
chore: provide secrets
kptdobe Dec 22, 2025
e43b2a6
chore: output user
kptdobe Dec 22, 2025
0856c84
chore: back to green
kptdobe Dec 23, 2025
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
8 changes: 7 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ jobs:
run: npm run test
- name: Run the integration tests
run: npm run test:it

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
Expand Down Expand Up @@ -64,6 +63,13 @@ jobs:

- name: Post-Deployment Integration Test
run: npm run test:postdeploy
env:
IT_IMS_STAGE_ENDPOINT: ${{ secrets.IT_IMS_STAGE_ENDPOINT }}
IT_IMS_STAGE_CLIENT_ID_LIMITED_USER: ${{ secrets.IT_IMS_STAGE_CLIENT_ID_LIMITED_USER }}
IT_IMS_STAGE_CLIENT_SECRET_LIMITED_USER: ${{ secrets.IT_IMS_STAGE_CLIENT_SECRET_LIMITED_USER }}
IT_IMS_STAGE_CLIENT_ID_SUPER_USER: ${{ secrets.IT_IMS_STAGE_CLIENT_ID_SUPER_USER }}
IT_IMS_STAGE_CLIENT_SECRET_SUPER_USER: ${{ secrets.IT_IMS_STAGE_CLIENT_SECRET_SUPER_USER }}
IT_IMS_STAGE_SCOPES: ${{ secrets.IT_IMS_STAGE_SCOPES }}
- name: Semantic Release (Dry Run)
run: npm run semantic-release-dry
env:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ coverage

# Wrangler temp
.wrangler
wrangler-versioned.toml
.deployment-env

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
Expand Down
73 changes: 73 additions & 0 deletions deploy-ci-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

# Copyright 2025 Adobe. All rights reserved.
# This file is licensed to you under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.

set -e

ENVIRONMENT="ci"

# Prepare version and capture version
echo "Preparing version for environment: $ENVIRONMENT"
VERSION=$(node prepare-deploy.js)

if [ -z "$VERSION" ]; then
echo "Error: Failed to get version from prepare-deploy.js"
exit 1
fi

# Get current git branch name
BRANCH=$(git rev-parse --abbrev-ref HEAD)

if [ -z "$BRANCH" ]; then
echo "Error: Failed to get git branch name"
exit 1
fi

echo "Creating version: $VERSION from branch: $BRANCH"

# Deploy with branch tag and version message and capture output
# wrangler deploy -e "$ENVIRONMENT" -c wrangler-versioned.toml --message "v$VERSION" --tag "$BRANCH"
OUTPUT=$(wrangler versions upload -e "$ENVIRONMENT" -c wrangler-versioned.toml --message "$ENVIRONMENT: v$VERSION - branch: $BRANCH" --tag "$BRANCH" 2>&1)

# Display the output
echo "$OUTPUT"

# Parse the deployment information
WORKER_VERSION_ID=$(echo "$OUTPUT" | grep "Worker Version ID:" | sed 's/.*Worker Version ID: //')
WORKER_PREVIEW_URL=$(echo "$OUTPUT" | grep "Version Preview URL:" | sed 's/.*Version Preview URL: //')

# Write to a file that can be sourced (for local use)
cat > .deployment-env << EOF
export WORKER_VERSION_ID="$WORKER_VERSION_ID"
export WORKER_PREVIEW_URL="$WORKER_PREVIEW_URL"
export WORKER_PREVIEW_BRANCH="$BRANCH"
EOF

# If running in GitHub Actions, also write to GITHUB_ENV
if [ -n "$GITHUB_ENV" ]; then
echo "WORKER_VERSION_ID=$WORKER_VERSION_ID" >> "$GITHUB_ENV"
echo "WORKER_PREVIEW_URL=$WORKER_PREVIEW_URL" >> "$GITHUB_ENV"
echo "WORKER_PREVIEW_BRANCH=$BRANCH" >> "$GITHUB_ENV"
echo "Variables exported to GitHub Actions environment"
fi

# Deploy the version
wrangler versions deploy -y -e ci --version-id "$WORKER_VERSION_ID"

echo ""
echo "Version deployment complete!"
echo "----------------------------------------"
echo "Deployment information: (copy inside a .deployment-env file to run locally)"
echo "export WORKER_VERSION_ID=$WORKER_VERSION_ID"
echo "export WORKER_PREVIEW_URL=$WORKER_PREVIEW_URL"
echo "export WORKER_PREVIEW_BRANCH=$BRANCH"
echo "----------------------------------------"

135 changes: 135 additions & 0 deletions integration-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Integration Tests

The `da-admin` worker includes a suite of integration tests designed as "smoke tests". These tests validate:

- **Deployment Integrity**: Ensures the worker can be successfully deployed to the Cloudflare Workers runtime.
- **Core Functionality**: Verifies critical features such as authentication, read/write operations, and permission handling function correctly end-to-end.

## Architecture

The test entry point is [`./test/it/smoke.test.js`](./test/it/smoke.test.js), which sets up the environment and executes the test suite defined in [`./test/it/it-tests.js`](./test/it/it-tests.js). The tests can run in two modes:

1. **Local Mode**: Runs entirely on the local machine using mocks and local servers.
2. **Stage Mode**: Runs against a deployed version of the worker on Cloudflare (used in CI).

### 1. Local Mode

**Local Mode** is the default for development. It orchestrates a local environment consisting of:
- **`wrangler dev`**: Runs the `da-admin` worker locally.
- **`S3rver`**: A local S3-compatible object storage server to mock R2/S3.
- **Mock IMS Server**: A local HTTP server simulating Adobe IMS for authentication.

**Configuration:**
- Environment variables are automatically loaded from [`./.dev.vars.it`](./.dev.vars.it).
- No manual configuration is typically required.
- **Note**: In **Local Mode**, the DA configuration is ephemeral and set up before each test run.

**How to Run:**
```bash
npm run test:it
```

### 2. Stage Mode (CI/CD)

In **Stage Mode**, tests execute against a live worker deployed to Cloudflare. This verifies the actual deployment artifacts and Cloudflare environment behavior.

The tests create a repository `test-repo-<branchname>` under the `da-admin-ci-it-org` located in the `aem-content-stage` bucket. The config is predefined for this org and defines permissions for the test users (see below).

#### CI/CD Pipeline Flow

The GitHub Actions workflow executes these tests in two phases:

1. **Deployment**:
- `npm run deploy:ci`: Uploads a new version of the worker (tagged with the branch name) to the `ci` environment.
- Generates a `.deployment-env` file containing the `WORKER_VERSION_ID`, `WORKER_PREVIEW_URL` and `WORKER_PREVIEW_BRANCH`.

2. **Verification**:
- `npm run test:postdeploy`: Sources the `.deployment-env` file and runs the test suite.
- When `WORKER_PREVIEW_URL` is present in the environment, [`smoke.test.js`](./test/it/smoke.test.js) switches to **Stage Mode**.
- Tests authenticates against a real IMS environment (Stage/Prod) and requests are sent to the deployed worker.

#### Running Stage Tests Locally

To debug CI failures or test against a deployed worker from your local machine:

1. **Deploy the Worker**:
```bash
npm run deploy:ci
```
This script will generate the `.deployment-env` file in your root directory.

2. **Configure Credentials**:
Create a `.env` file (or set environment variables) with the required IMS credentials for the test accounts:
```env
IT_IMS_STAGE_ENDPOINT=https://ims-na1.adobelogin.com
IT_IMS_STAGE_CLIENT_ID_SUPER_USER=<client-id-super-user>
IT_IMS_STAGE_CLIENT_SECRET_SUPER_USER=<client-secret-super-user>
IT_IMS_STAGE_CLIENT_ID_LIMITED_USER=<client-id-limited-user>
IT_IMS_STAGE_CLIENT_SECRET_LIMITED_USER=<client-secret-limited-user>
IT_IMS_STAGE_SCOPES=openid,AdobeID,aem.frontend.all,read_organizations,additional_info.projectedProductContext
```

3. **Run the Tests**:
```bash
# Loads the deployment vars and runs the tests
npm run test:postdeploy2
```

### Persistence & Configuration

In **Stage Mode**, the tests rely on the `DA_CONFIG_STAGE` KV storage for permissions. This configuration is persistent.

If the configuration is lost or needs to be reset, the expected permission model is:

```json
{
"total": 2,
"limit": 2,
"offset": 0,
"data": [
{
"path": "CONFIG",
"groups": "<super-user-email>",
"actions": "write"
},
{
"path": "/+**",
"groups": "<super-user-email>",
"actions": "write"
}
],
":type": "sheet",
":sheetname": "permissions"
}
```

## IMS Configuration

In **Stage Mode**, tests execute against the **IMS Stage** environment.

### Prerequisites

1. **Worker Configuration**: The `IMS_ORIGIN` secret for the `da-admin` worker (CI environment) must point to the IMS Stage endpoint.
2. **User Existence**: Test users must exist and belong to an IMS Stage organization. No specific organization permissions are required beyond basic membership.
3. **DA Configuration**: The test users must be explicitly granted permissions in the `DA_CONFIG` (as shown in the [Persistence & Configuration](#persistence--configuration) section).

### Test Users Setup

The integration tests use dedicated service accounts defined in the [Adobe Stage Developer Console](https://developer-stage.adobe.com/) (VPN required) under the `Document Authoring Stage` organization. Two distinct projects were created to simulate different user roles:

- **Authenticated User Project**:
- **Purpose**: Simulates a user who is logged in but may not have specific permissions (used for negative testing or basic access).
- **Credentials**: Defined in CI secrets as `IT_IMS_STAGE_CLIENT_ID_SUPER_USER` / `IT_IMS_STAGE_CLIENT_SECRET_SUPER_USER`.
- **API**: Uses `Edge Delivery Service` to create OAuth Server-to-Server credentials.

- **Authorized User Project**:
- **Purpose**: Simulates a user with full read/write permissions.
- **Credentials**: (Currently the tests primarily use one set of credentials which are authorized in the config).
- **API**: Uses `Edge Delivery Service` to create OAuth Server-to-Server credentials.

> **Notes on Setup:**
> 1. **Multiple Projects**: Two separate projects were created because generating multiple independent credentials within a single project was not supported.
> 2. **Role Distinction**: The distinction between "authenticated" and "authorized" is managed entirely within the `DA_CONFIG` permissions sheet, not in IMS. The project naming reflects the intended use case.
> 3. **API Selection**: The `Edge Delivery Service` API was selected for convenience. Any API service can be used provided it:
> - Supports IMS connection.
> - Includes the `read_organizations` scope.
Loading