diff --git a/.changeset/staging-ci-cd-docs.md b/.changeset/staging-ci-cd-docs.md new file mode 100644 index 000000000..d83165704 --- /dev/null +++ b/.changeset/staging-ci-cd-docs.md @@ -0,0 +1,5 @@ +--- +'@salesforce/b2c-dx-docs': patch +--- + +Document deploying to staging environments (two-factor mTLS) from CI/CD. The `setup` GitHub Action now accepts `webdav-server`, `certificate`, `certificate-passphrase`, and `selfsigned` inputs so workflows can target staging instances that require a separate WebDAV hostname and a client certificate. The CI/CD guide includes a full GitHub Actions example using a base64-encoded `.p12` secret. diff --git a/actions/README.md b/actions/README.md index ebef825aa..f95b24c8b 100644 --- a/actions/README.md +++ b/actions/README.md @@ -100,6 +100,12 @@ All actions accept auth inputs directly or read from `SFCC_*` environment variab | `mrt-project` | `MRT_PROJECT` | MRT operations | | `mrt-environment` | `MRT_ENVIRONMENT` | MRT operations | | `account-manager-host` | `SFCC_ACCOUNT_MANAGER_HOST` | Account Manager | +| `webdav-server` | `SFCC_WEBDAV_SERVER` | Staging WebDAV (cert. hostname) | +| `certificate` | `SFCC_CERTIFICATE` | Two-factor mTLS (PKCS12 path) | +| `certificate-passphrase` | `SFCC_CERTIFICATE_PASSPHRASE` | Two-factor mTLS | +| `selfsigned` | `SFCC_SELFSIGNED` | Allow self-signed server certs | + +For staging environments that require a separate WebDAV hostname and a client certificate, see the [Staging Environments guide](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/ci-cd.html#staging-environments-two-factor-mtls) for the full pattern (decoding a base64-encoded `.p12` from a secret + wiring it through `setup`). ## Plugins diff --git a/actions/setup/action.yml b/actions/setup/action.yml index 0e74e1c95..eb163bc4f 100644 --- a/actions/setup/action.yml +++ b/actions/setup/action.yml @@ -49,6 +49,18 @@ inputs: account-manager-host: description: 'Account Manager hostname → SFCC_ACCOUNT_MANAGER_HOST' required: false + webdav-server: + description: 'Separate WebDAV hostname (used for staging cert. hostnames) → SFCC_WEBDAV_SERVER' + required: false + certificate: + description: 'Path to PKCS12 client certificate for two-factor (mTLS) auth → SFCC_CERTIFICATE' + required: false + certificate-passphrase: + description: 'Passphrase for the PKCS12 client certificate → SFCC_CERTIFICATE_PASSPHRASE' + required: false + selfsigned: + description: 'Allow self-signed server certificates → SFCC_SELFSIGNED. Set to "true" to enable; omit otherwise.' + required: false log-level: description: 'CLI log level (trace, debug, info, warn, error, silent) → SFCC_LOG_LEVEL' required: false @@ -127,6 +139,22 @@ runs: if [ -n "${{ inputs.account-manager-host }}" ]; then echo "SFCC_ACCOUNT_MANAGER_HOST=${{ inputs.account-manager-host }}" >> "$GITHUB_ENV" fi + if [ -n "${{ inputs.webdav-server }}" ]; then + echo "SFCC_WEBDAV_SERVER=${{ inputs.webdav-server }}" >> "$GITHUB_ENV" + fi + if [ -n "${{ inputs.certificate }}" ]; then + echo "SFCC_CERTIFICATE=${{ inputs.certificate }}" >> "$GITHUB_ENV" + fi + if [ -n "${{ inputs.certificate-passphrase }}" ]; then + echo "SFCC_CERTIFICATE_PASSPHRASE=${{ inputs.certificate-passphrase }}" >> "$GITHUB_ENV" + fi + # Only export SFCC_SELFSIGNED when explicitly truthy. The SDK's env-var + # source treats only "true"/"1" as enabling self-signed mode, but oclif + # boolean flags map any non-empty env value to true. Skipping export for + # other values avoids that asymmetry — leaving the flag at its default. + if [ "${{ inputs.selfsigned }}" = "true" ] || [ "${{ inputs.selfsigned }}" = "1" ]; then + echo "SFCC_SELFSIGNED=true" >> "$GITHUB_ENV" + fi if [ -n "${{ inputs.log-level }}" ]; then echo "SFCC_LOG_LEVEL=${{ inputs.log-level }}" >> "$GITHUB_ENV" fi diff --git a/docs/guide/ci-cd.md b/docs/guide/ci-cd.md index 4de5cfd92..35cda88b9 100644 --- a/docs/guide/ci-cd.md +++ b/docs/guide/ci-cd.md @@ -125,6 +125,30 @@ Installs the CLI and writes credentials to environment variables. Use this when Plugins are installed after the CLI and cached across runs. Each line is an npm package name or GitHub `owner/repo`. +The setup action accepts the following inputs (each maps to the corresponding `SFCC_*` environment variable): + +| Input | Environment Variable | +|-------|---------------------| +| `client-id` | `SFCC_CLIENT_ID` | +| `client-secret` | `SFCC_CLIENT_SECRET` | +| `server` | `SFCC_SERVER` | +| `code-version` | `SFCC_CODE_VERSION` | +| `username` | `SFCC_USERNAME` | +| `password` | `SFCC_PASSWORD` | +| `short-code` | `SFCC_SHORTCODE` | +| `tenant-id` | `SFCC_TENANT_ID` | +| `account-manager-host` | `SFCC_ACCOUNT_MANAGER_HOST` | +| `webdav-server` | `SFCC_WEBDAV_SERVER` | +| `certificate` | `SFCC_CERTIFICATE` | +| `certificate-passphrase` | `SFCC_CERTIFICATE_PASSPHRASE` | +| `selfsigned` | `SFCC_SELFSIGNED` | +| `mrt-api-key` | `MRT_API_KEY` | +| `mrt-project` | `MRT_PROJECT` | +| `mrt-environment` | `MRT_ENVIRONMENT` | +| `log-level` | `SFCC_LOG_LEVEL` | + +The `webdav-server`, `certificate`, `certificate-passphrase`, and `selfsigned` inputs are only needed for staging environments that require a separate WebDAV hostname and a client certificate (mTLS). See [Staging Environments (Two-Factor mTLS)](#staging-environments-two-factor-mtls). + ### Run ``` @@ -277,6 +301,117 @@ Upload files via WebDAV. | `remote-path` | *(required)* | Remote destination path | | `root` | `IMPEX` | WebDAV root (IMPEX, TEMP, CARTRIDGES, etc.) | +## Staging Environments (Two-Factor mTLS) + +Internal staging instances typically require: + +- A separate WebDAV hostname (often a `cert.*` variant of the main hostname) +- A PKCS12 (`.p12`) client certificate with passphrase for mutual TLS +- Permission to accept self-signed server certificates + +See [Two-Factor Authentication (mTLS)](/guide/configuration#two-factor-authentication-mtls) for the underlying configuration model. + +### CLI Flags + +The same options that go in `dw.json` are available as CLI flags. For local use against a staging instance: + +```bash +b2c code deploy \ + --server staging-internal-ccdemo.demandware.net \ + --webdav-server cert.staging.internal.ccdemo.demandware.net \ + --certificate /path/to/STG-2FA-ccdemo/deploy.p12 \ + --passphrase 'your-cert-passphrase' \ + --selfsigned \ + --client-id "$SFCC_CLIENT_ID" \ + --client-secret "$SFCC_CLIENT_SECRET" +``` + +| Flag | dw.json Field | Environment Variable | +|------|---------------|---------------------| +| `--server` | `hostname` | `SFCC_SERVER` | +| `--webdav-server` | `webdav-hostname` | `SFCC_WEBDAV_SERVER` | +| `--certificate` | `certificate` | `SFCC_CERTIFICATE` | +| `--passphrase` | `certificate-passphrase` | `SFCC_CERTIFICATE_PASSPHRASE` | +| `--selfsigned` | `self-signed` | `SFCC_SELFSIGNED` | + +### GitHub Actions + +Staging mTLS works with the standard actions — the `setup` action accepts `webdav-server`, `certificate`, `certificate-passphrase`, and `selfsigned` inputs alongside the usual auth inputs. + +Because the `.p12` is a binary file, store it as a base64-encoded GitHub secret and decode it to disk in a workflow step before calling `setup`. The `certificate` input then points at the decoded path. + +**Recommended secrets/variables for staging:** + +| Secret | Description | +|--------|-------------| +| `SFCC_STAGING_CERTIFICATE_P12_BASE64` | Base64-encoded `.p12` client certificate | +| `SFCC_STAGING_CERTIFICATE_PASSPHRASE` | Passphrase for the `.p12` | +| `SFCC_CLIENT_ID` / `SFCC_CLIENT_SECRET` | OAuth credentials | + +| Variable | Description | +|----------|-------------| +| `SFCC_STAGING_SERVER` | e.g. `staging-internal-ccdemo.demandware.net` | +| `SFCC_STAGING_WEBDAV_SERVER` | e.g. `cert.staging.internal.ccdemo.demandware.net` | + +To create the base64 secret locally: + +```bash +base64 -i deploy.p12 | pbcopy # macOS +# or +base64 -w0 deploy.p12 # Linux +``` + +Then paste the value into a GitHub repository secret. + +**Workflow example:** + +```yaml +name: Deploy to Staging + +on: + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # Decode the .p12 to a file inside the runner workspace + - name: Decode staging client certificate + run: | + echo "${{ secrets.SFCC_STAGING_CERTIFICATE_P12_BASE64 }}" \ + | base64 --decode > "$RUNNER_TEMP/staging-deploy.p12" + chmod 600 "$RUNNER_TEMP/staging-deploy.p12" + + - uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/setup@v1 + with: + client-id: ${{ secrets.SFCC_CLIENT_ID }} + client-secret: ${{ secrets.SFCC_CLIENT_SECRET }} + server: ${{ vars.SFCC_STAGING_SERVER }} + webdav-server: ${{ vars.SFCC_STAGING_WEBDAV_SERVER }} + certificate: ${{ runner.temp }}/staging-deploy.p12 + certificate-passphrase: ${{ secrets.SFCC_STAGING_CERTIFICATE_PASSPHRASE }} + selfsigned: 'true' + + - run: npm ci && npm run build + + - uses: SalesforceCommerceCloud/b2c-developer-tooling/actions/code-deploy@v1 + with: + code-version: staging-${{ github.run_number }} + activate: true +``` + +Once the `setup` step writes `SFCC_CERTIFICATE`, `SFCC_WEBDAV_SERVER`, etc. to `$GITHUB_ENV`, every subsequent action picks them up automatically — no need to repeat them on `code-deploy`, `data-import`, `job-run`, or `webdav-upload`. + +::: tip Multiple Environments in One Workflow +If a single workflow targets both a normal sandbox and a staging instance, run `setup` again before each phase with the appropriate inputs. The second `setup` only overrides env vars for inputs you actually pass — anything left blank keeps its value from the previous `setup`. To fully switch environments, re-pass every variable that should change (or use the `env:` block on individual steps to scope overrides). +::: + +::: warning Cleanup +The decoded `.p12` lives only inside the runner's ephemeral workspace and is destroyed when the job ends. Never commit the file or write it outside `$RUNNER_TEMP` / the workspace. +::: + ## Patterns ### Data Import Pipeline diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index d82903484..5695a83d2 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -290,6 +290,12 @@ For instances that require client certificate authentication: The certificate must be in PKCS12 format (`.p12` or `.pfx`). The `self-signed` option is often needed for staging environments with internal certificates. +The same fields are available as CLI flags (`--webdav-server`, `--certificate`, `--passphrase`, `--selfsigned`) and as environment variables (`SFCC_WEBDAV_SERVER`, `SFCC_CERTIFICATE`, `SFCC_CERTIFICATE_PASSPHRASE`, `SFCC_SELFSIGNED`). + +::: tip Running staging deploys in CI/CD +For GitHub Actions workflows that target staging — including how to handle the `.p12` certificate as a base64-encoded secret — see [Staging Environments (Two-Factor mTLS)](/guide/ci-cd#staging-environments-two-factor-mtls). +::: + ::: tip MRT Configuration MRT API key can also be loaded from `~/.mobify`. See [MRT API Key](#mrt-api-key) below. :::