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
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ main() {
local expected
for expected in \
'token=dummy-token' \
'service-id=dummy-service' \
'service-id=dummyservice' \
'endpoint=CLEARED' \
'home=CLEARED' \
'action-token-carrier=CLEARED' \
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/deploy-core/tests/assert-rollback-calls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ main() {
local log="${FAKE_CALL_LOG:?FAKE_CALL_LOG is required}"
local staged="${EDGEZERO__TEST__STAGED_VERSION:?EDGEZERO__TEST__STAGED_VERSION is required}"
local rolled_back_to="${EDGEZERO__TEST__ROLLED_BACK_TO:-}"
local api='https://api\.fastly\.com/service/dummy-service'
local api='https://api\.fastly\.com/service/dummyservice'
# The EXPLICIT rollback-to the smoke passes to the production rollback (it rolls
# back FROM the active version 40 TO 39; the best-effort staleness guard requires the
# rolled-back-from version to still be active).
Expand Down
14 changes: 7 additions & 7 deletions .github/actions/deploy-core/tests/assert-staged-calls.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ assert_comment_precedes_stage() {
fail "the comment was applied after staging; it must precede it"
}

# The staging twin must MIRROR production's runtime overrides: the non-config
# override (LOG_LEVEL) is copied verbatim and the config selector is redirected
# to `<logical>_staging`, both written into the twin (STAGESEL1) before the
# relink. Without the mirror the staged version would lose production's adapter /
# logging overrides.
# The staging twin must MIRROR this service's production runtime overrides: the
# scoped logging level is copied verbatim and the scoped config selector is
# redirected to `<logical>_staging`, both written into the twin (STAGESEL1)
# before the relink. Without the mirror the staged version would lose its
# production logging override.
assert_twin_mirrors_production() {
local log="$1"
grep -qE '^fastly config-store-entry update .*--store-id=STAGESEL1 .*--key=EDGEZERO__ADAPTER__FASTLY__LOG_LEVEL' "$log" ||
grep -qE '^fastly config-store-entry update .*--store-id=STAGESEL1 .*--key=EDGEZERO__SERVICES__dummyservice__LOGGING__LEVEL' "$log" ||
fail "production's non-config override was not mirrored into the staging twin"
grep -qE '^fastly config-store-entry update .*--store-id=STAGESEL1 .*--key=EDGEZERO__STORES__CONFIG__APP_CONFIG__KEY' "$log" ||
grep -qE '^fastly config-store-entry update .*--store-id=STAGESEL1 .*--key=EDGEZERO__SERVICES__dummyservice__STORES__CONFIG__APP_CONFIG__KEY' "$log" ||
fail "the config selector was not written into the staging twin"

# The mirror must land before the relink points the draft at the twin.
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/deploy-core/tests/assert-staging-probe.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ main() {
local healthy="${EDGEZERO__TEST__HEALTHY:-}"
local status_code="${EDGEZERO__TEST__STATUS_CODE:-}"

grep -qE "^GET https://api\.fastly\.com/service/dummy-service/version/$staged/domain\?include=staging_ips\$" "$log" ||
grep -qE "^GET https://api\.fastly\.com/service/dummyservice/version/$staged/domain\?include=staging_ips\$" "$log" ||
fail "the staging-IP lookup was never performed for version $staged"

grep -qE '^PROBE .*--connect-to ::151\.101\.2\.10:443 .*https://staging\.example\.com/' "$log" ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ main() {
local state="${FAKE_ACTIVE_VERSION_FILE:?FAKE_ACTIVE_VERSION_FILE is required}"
local outcome="${EDGEZERO__TEST__OUTCOME:?EDGEZERO__TEST__OUTCOME is required}"
local snapshot="${EDGEZERO__TEST__LOG_SNAPSHOT:?EDGEZERO__TEST__LOG_SNAPSHOT is required}"
local api='https://api\.fastly\.com/service/dummy-service'
local api='https://api\.fastly\.com/service/dummyservice'

[[ "$outcome" == "failure" ]] ||
fail "a stale production rollback must fail (the rolled-back-from version is no longer active), got outcome=$outcome"
Expand Down
12 changes: 6 additions & 6 deletions .github/actions/deploy-core/tests/make-fake-fastly-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ case "\${1:-} \${2:-}" in
"compute update")
# A realistic success line: the version parser is fail-closed and will
# refuse to stage if it cannot read a version out of this output.
echo "SUCCESS: Updated package (service dummy-service, version 42)"
echo "SUCCESS: Updated package (service dummyservice, version 42)"
;;
"compute deploy") echo "SUCCESS: Deployed package (service dummy-service, version 43)" ;;
"compute deploy") echo "SUCCESS: Deployed package (service dummyservice, version 43)" ;;
"service-version update") echo "Updated version comment" ;;
"service-version stage") echo "Staged version" ;;
# An app WITH config selection: the app config store, the production selector
# store edgezero_runtime_env (so a staged deploy relinks rather than skipping),
# and its staging twin (the store the relink points at). config push resolves a
# store id by name from this list, reads the current entry to diff, then upserts.
"config-store list") echo '[{"id":"STOREID1","name":"app_config"},{"id":"ENVSEL1","name":"edgezero_runtime_env"},{"id":"STAGESEL1","name":"edgezero_runtime_env_staging_dummy-service"}]' ;;
"config-store list") echo '[{"id":"STOREID1","name":"app_config"},{"id":"ENVSEL1","name":"edgezero_runtime_env"},{"id":"STAGESEL1","name":"edgezero_runtime_env_staging_dummyservice"}]' ;;
# A cloned draft inherits the active version's links; the staged deploy drops
# this one and re-links the staging store under the same name.
"resource-link list") echo '[{"id":"LINK_ENV","name":"edgezero_runtime_env"}]' ;;
Expand All @@ -69,10 +69,10 @@ case "\${1:-} \${2:-}" in
;;
"config-store-entry list")
# A staged deploy MIRRORS the production selector store into the staging twin.
# Production (ENVSEL1) carries a non-config override the twin must copy
# verbatim; the twin (STAGESEL1) starts empty.
# Production (ENVSEL1) carries this service's scoped logging override, which
# the twin must copy verbatim; the twin (STAGESEL1) starts empty.
case "\$*" in
*--store-id=ENVSEL1*) echo '[{"item_key":"EDGEZERO__ADAPTER__FASTLY__LOG_LEVEL","item_value":"debug"}]' ;;
*--store-id=ENVSEL1*) echo '[{"item_key":"EDGEZERO__SERVICES__dummyservice__LOGGING__LEVEL","item_value":"debug"}]' ;;
*) echo '[]' ;;
esac
;;
Expand Down
4 changes: 3 additions & 1 deletion .github/actions/deploy-core/tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ test_wrapper_validate() {
run_dfl() {
env EDGEZERO__APP__CLI__ARTIFACT_PRESENT="${A:-true}" \
EDGEZERO__FASTLY__API_TOKEN_PRESENT="${T:-true}" \
EDGEZERO__FASTLY__SERVICE_ID="${S-svc_1}" \
EDGEZERO__FASTLY__SERVICE_ID="${S-svc1}" \
EDGEZERO__ADAPTER=fastly EDGEZERO__RUNNER__OS=Linux EDGEZERO__RUNNER__ARCH=X64 \
EDGEZERO__ACTION__STATE_DIR="$WORK_DIR/dfl-state" \
GITHUB_OUTPUT="$WORK_DIR/dfl-out.txt" \
Expand All @@ -424,6 +424,8 @@ test_wrapper_validate() {
A=false assert_fails "deploy-fastly: missing artifact is rejected" run_dfl
T=false assert_fails "deploy-fastly: missing token (by presence) is rejected" run_dfl
S='bad id!' assert_fails "deploy-fastly: malformed service-id is rejected" run_dfl
S='svc_1' assert_fails "deploy-fastly: service-id with underscore is rejected" run_dfl
S='svc-1' assert_fails "deploy-fastly: service-id with hyphen is rejected" run_dfl
S='' assert_fails "deploy-fastly: empty service-id is rejected" run_dfl

# config-push-fastly: artifact + token presence, deploy-to fail-closed.
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/deploy-fastly/scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ main() {
local service_id="${EDGEZERO__FASTLY__SERVICE_ID:-}"

require_input fastly-api-token "$token"
require_input_matching fastly-service-id "$service_id" '^[A-Za-z0-9_-]+$'
require_input_matching fastly-service-id "$service_id" '^[A-Za-z0-9]+$'
require_cmd jq

EDGEZERO__PROVIDER__ENV=$(jq -n --arg t "$token" --arg s "$service_id" \
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/deploy-fastly/scripts/validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ main() {
# run, so the CLI we then execute with credentials would be arbitrary.
require_present app-cli-artifact "${EDGEZERO__APP__CLI__ARTIFACT_PRESENT:-}"
require_present fastly-api-token "${EDGEZERO__FASTLY__API_TOKEN_PRESENT:-}"
require_input_matching fastly-service-id "${EDGEZERO__FASTLY__SERVICE_ID:-}" '^[A-Za-z0-9_-]+$'
require_input_matching fastly-service-id "${EDGEZERO__FASTLY__SERVICE_ID:-}" '^[A-Za-z0-9]+$'

# Provider-neutral validation (adapter, booleans, JSON-array args, the
# allowlist). It also rejects a 'deploy-to' that is neither production nor
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/healthcheck-fastly/scripts/healthcheck.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ validate_inputs() {
require_linux_x86_64
# `required: true` in action metadata does not fail an omitted input, so the
# only real guard against probing with an empty service/version is this one.
require_input_matching fastly-service-id "${EDGEZERO__LIFECYCLE__SERVICE_ID:-}" '^[A-Za-z0-9_-]+$'
require_input_matching fastly-service-id "${EDGEZERO__LIFECYCLE__SERVICE_ID:-}" '^[A-Za-z0-9]+$'
require_input_matching fastly-version "${EDGEZERO__LIFECYCLE__VERSION:-}" '^[0-9]+$'
require_input_matching domain "${EDGEZERO__LIFECYCLE__DOMAIN:-}" '^[A-Za-z0-9._-]+$'
# The path is appended to https://<domain> as one curl argument (the CLI
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/rollback-fastly/scripts/rollback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ source "$SCRIPT_DIR/../../deploy-core/scripts/common.sh"

validate_inputs() {
require_linux_x86_64
require_input_matching fastly-service-id "${EDGEZERO__LIFECYCLE__SERVICE_ID:-}" '^[A-Za-z0-9_-]+$'
require_input_matching fastly-service-id "${EDGEZERO__LIFECYCLE__SERVICE_ID:-}" '^[A-Za-z0-9]+$'
require_input_matching fastly-version "${EDGEZERO__LIFECYCLE__VERSION:-}" '^[0-9]+$'
require_input fastly-api-token "${FASTLY_API_TOKEN:-}"
# A typo in deploy-to must never silently roll back production.
Expand Down
36 changes: 18 additions & 18 deletions .github/workflows/deploy-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
deploy-args: '["--comment","smoke"]'

- name: Assert production deploy, version threading, and credential boundary
Expand All @@ -197,7 +197,7 @@ jobs:
with:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
fastly-version: ${{ steps.deploy.outputs['fastly-version'] }}
rollback-to: ${{ steps.deploy.outputs['previous-version'] }}
deploy-to: production
Expand Down Expand Up @@ -254,7 +254,7 @@ jobs:
app-cli-artifact: edgezero-cli-handoff
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
- name: Assert the cross-job handoff produced a real production deploy
env:
EDGEZERO__TEST__FASTLY_VERSION: ${{ steps.deploy.outputs['fastly-version'] }}
Expand Down Expand Up @@ -290,7 +290,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
build-mode: always
cache: true
- name: Capture the seeded marker, then delete target/
Expand All @@ -301,7 +301,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
build-mode: always
cache: true
- name: Assert the marker was restored from cache (not rebuilt)
Expand All @@ -318,7 +318,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
build-mode: never
cache: true
- name: Assert the cache was NOT restored under build-mode never
Expand Down Expand Up @@ -359,7 +359,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
- name: Assert the deploy failed but signalled a possible mutation
env:
EDGEZERO__TEST__DEPLOY_OUTCOME: ${{ steps.deploy.outcome }}
Expand All @@ -377,15 +377,15 @@ jobs:
id: recover
env:
FASTLY_API_TOKEN: dummy-token
FASTLY_SERVICE_ID: dummy-service
FASTLY_SERVICE_ID: dummyservice
run: .github/actions/deploy-core/tests/recovery-active-version.sh recover-cli
- name: Roll back to the captured previous version, keyed on the recovered live version
id: rollback
uses: ./.github/actions/rollback-fastly
with:
app-cli-artifact: edgezero-cli-recovery
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
fastly-version: ${{ steps.recover.outputs.version }}
# Thread the deploy's OWN previous-version output (captured pre-mutation),
# exactly as the guide's recovery documents — not a hardcoded value.
Expand Down Expand Up @@ -521,7 +521,7 @@ jobs:
app-cli-artifact: ${{ steps.cli.outputs.app-cli-artifact }}
working-directory: fixture-app
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
deploy-args: '["--comment","staged smoke"]'
deploy-to: staging

Expand All @@ -539,7 +539,7 @@ jobs:
domain: staging.example.com
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
retry: "1"
retry-delay: "1"

Expand All @@ -560,7 +560,7 @@ jobs:
domain: staging.example.com
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice
retry: "1"
retry-delay: "1"
env:
Expand Down Expand Up @@ -588,7 +588,7 @@ jobs:
deploy-to: production
domain: staging.example.com
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-service-id: dummy-service
fastly-service-id: dummyservice
retry: "1"
retry-delay: "1"

Expand All @@ -609,7 +609,7 @@ jobs:
deploy-to: staging
domain: staging.example.com
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-service-id: dummy-service
fastly-service-id: dummyservice
retry: "1"
retry-delay: "1"

Expand All @@ -627,7 +627,7 @@ jobs:
deploy-to: staging
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice

- name: Roll back production
id: prod-rollback
Expand All @@ -643,7 +643,7 @@ jobs:
fastly-version: "40"
rollback-to: "39"
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice

- name: Assert rollback verbs, paths, and version threading
env:
Expand All @@ -662,7 +662,7 @@ jobs:
deploy-to: production
fastly-version: ${{ steps.stage.outputs['fastly-version'] }}
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice

- name: Assert the targetless production rollback was refused
env:
Expand Down Expand Up @@ -691,7 +691,7 @@ jobs:
fastly-version: "40"
rollback-to: "38"
fastly-api-token: dummy-token
fastly-service-id: dummy-service
fastly-service-id: dummyservice

- name: Assert the stale rollback was refused and activated nothing
env:
Expand Down
Loading
Loading