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
33 changes: 33 additions & 0 deletions .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: docs-deploy

on:
push:
branches:
- main
paths:
- '.github/workflows/docs.yml'
- '.github/workflows/docs-deploy.yml'
- 'docs/**'
- 'zensical.toml'
- 'pyproject.toml'
- 'src/common_python_tasks/tasks.py'
workflow_dispatch:

concurrency:
group: github-pages
cancel-in-progress: false

jobs:
docs:
uses: ./.github/workflows/docs.yml
with:
python_version: '3.14'
dependency_group: ''
locked: false
artifact_name: common-python-tasks-docs
generated_docs_check_task: check-docs-references
deploy_github_pages: true
permissions:
contents: read
pages: write
id-token: write
124 changes: 124 additions & 0 deletions .github/workflows/docs-preview-cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: docs-preview-cleanup

on:
pull_request:
types:
- closed

jobs:
cleanup:
name: Remove Cloudflare Pages preview
if: vars.CLOUDFLARE_PAGES_PROJECT != ''
runs-on: ubuntu-latest
permissions:
contents: read
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_PROJECT_NAME: ci-sourcerer-common-python-tasks
CLOUDFLARE_PREVIEW_BRANCH: pr-${{ github.event.pull_request.number }}
CLOUDFLARE_PREVIEW_DOMAIN: common-python-tasks.ci-sourcerer.com
CLOUDFLARE_PREVIEW_ZONE: ci-sourcerer.com
steps:
- name: Delete Cloudflare Pages preview deployments
run: |
if [[ -z "$CLOUDFLARE_ACCOUNT_ID" || -z "$CLOUDFLARE_API_TOKEN" ]]; then
echo "Cloudflare Pages cleanup skipped because credentials are unavailable."
exit 0
fi

project_url="https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PROJECT_NAME"
project_status="$(curl --silent --show-error --output /dev/null --write-out '%{http_code}' \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"$project_url")"
case "$project_status" in
200)
;;
404)
echo "Cloudflare Pages project does not exist; no preview deployments to remove."
exit 0
;;
*)
echo "Could not retrieve Cloudflare Pages project (HTTP $project_status)." >&2
exit 1
;;
esac

if [[ -n "$CLOUDFLARE_PREVIEW_DOMAIN" ]]; then
custom_domain="$CLOUDFLARE_PREVIEW_BRANCH.$CLOUDFLARE_PREVIEW_DOMAIN"
pages_target="$CLOUDFLARE_PREVIEW_BRANCH.$CLOUDFLARE_PROJECT_NAME.pages.dev"
if [[ -z "$CLOUDFLARE_PREVIEW_ZONE" ]]; then
CLOUDFLARE_PREVIEW_ZONE="$CLOUDFLARE_PREVIEW_DOMAIN"
fi
zone_response="$(curl --fail --silent --show-error \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones?name=$CLOUDFLARE_PREVIEW_ZONE")"
zone_id="$(jq --raw-output '.result[0].id // empty' <<< "$zone_response")"
if [[ -z "$zone_id" ]]; then
echo "No Cloudflare zone exists for $CLOUDFLARE_PREVIEW_ZONE." >&2
exit 1
fi

record_response="$(curl --fail --silent --show-error \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records?type=CNAME&name=$custom_domain")"
record_id="$(jq --raw-output --arg content "$pages_target" \
'.result[] | select(.content | rtrimstr(".") == $content) | .id' \
<<< "$record_response")"
if [[ -n "$record_id" ]]; then
curl --fail --silent --show-error \
--request DELETE \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id" > /dev/null
fi

domain_status="$(curl --silent --show-error --output /dev/null --write-out '%{http_code}' \
--request DELETE \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/$CLOUDFLARE_PROJECT_NAME/domains/$custom_domain")"
case "$domain_status" in
200|202|204|404)
;;
*)
echo "Could not remove Cloudflare Pages custom domain (HTTP $domain_status)." >&2
exit 1
;;
esac
fi

deployment_ids=()
page=1
while true; do
response="$(curl --fail --silent --show-error \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"$project_url/deployments?env=preview&page=$page&per_page=100")"
while IFS= read -r deployment_id; do
deployment_ids+=("$deployment_id")
done < <(jq --raw-output --arg branch "$CLOUDFLARE_PREVIEW_BRANCH" \
'.result[] | select(.deployment_trigger.metadata.branch == $branch) | .id' \
<<< "$response")
total_pages="$(jq --raw-output '.result_info.total_pages // 1' <<< "$response")"
if (( page >= total_pages )); then
break
fi
((page++))
done

for deployment_id in "${deployment_ids[@]}"; do
delete_status="$(curl --silent --show-error --output /dev/null --write-out '%{http_code}' \
--request DELETE \
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
"$project_url/deployments/$deployment_id?force=true")"
case "$delete_status" in
200|202|204|404)
echo "Removed Cloudflare Pages deployment $deployment_id."
;;
400)
echo "Cloudflare retained the latest Pages deployment for this branch."
;;
*)
echo "Could not remove Cloudflare Pages deployment $deployment_id (HTTP $delete_status)." >&2
exit 1
;;
esac
done
34 changes: 34 additions & 0 deletions .github/workflows/docs-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: docs-preview

on:
pull_request:
paths:
- '.github/workflows/docs.yml'
- '.github/workflows/docs-preview.yml'
- 'docs/**'
- 'zensical.toml'
- 'pyproject.toml'
- 'src/common_python_tasks/tasks.py'
workflow_dispatch:

jobs:
docs:
uses: ./.github/workflows/docs.yml
with:
python_version: '3.14'
dependency_group: ''
locked: false
artifact_name: common-python-tasks-docs
generated_docs_check_task: check-docs-references
publish_cloudflare: ${{ github.event_name == 'pull_request' && vars.CLOUDFLARE_PAGES_PROJECT != '' }}
cloudflare_project_name: ci-sourcerer-common-python-tasks
cloudflare_preview_domain: common-python-tasks.ci-sourcerer.com
cloudflare_preview_zone: ci-sourcerer.com
permissions:
contents: read
deployments: write
pages: write
id-token: write
secrets:
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
Loading
Loading