Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new Action to create GitHub deployments from Cloudflare #469

Merged
merged 4 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
29 changes: 29 additions & 0 deletions cloudflare-pages/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Cloudflare Pages Action

To use this Action please create a GitHub Actions workflow `.github/workflows/trigger-meticulous.yaml` with the contents:

```yaml
name: Trigger Meticulous
on: [push]
permissions:
deployments: write
jobs:
trigger-meticulous:
name: Trigger Meticulous
runs-on: ubuntu-latest
steps:
- name: Trigger Meticulous
uses: alwaysmeticulous/report-diffs-action/cloudflare-pages@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
cloudflare-api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare-account-id: << FILL THIS IN >>
cloudflare-project-name: << FILL THIS IN >>
```

You should pass in:

- `github-token`: This is automatically created for your workflow by GitHub but still needs to be passed in to our step as shown above.
- `cloudflare-api-token`: This should be created as documented [here](https://developers.cloudflare.com/pages/configuration/api/) with the `Read` permission for `Cloudflare Pages` and stored in a [GitHub Actions secret](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository) named `CLOUDFLARE_API_TOKEN`. Then it can be passed into our step as shown above.
- `cloudflare-account-id`: You can find this by following the instructions [here](https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/#find-account-id-workers-and-pages), then paste it into the workflow file (it is not confidential).
- `cloudflare-project-name`: You can find this on the same dashboard your account ID is on, then paste it into the workflow file (it is not confidential).
62 changes: 62 additions & 0 deletions cloudflare-pages/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: 'Meticulous - Trigger tests for Cloudflare Pages'
description: 'Trigger Meticulous tests for a Cloudflare Pages deployment'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

naming nit: I think a name that relates to how the action works, ie something like 'create a deployment from CF pages preview environment'. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

inputs:
github-token:
description: 'A GitHub Actions token (should have write permission on deployments)'
required: true
cloudflare-api-token:
description: 'API token for Cloudflare (should have Read permission for Cloudflare Pages)'
required: true
cloudflare-account-id:
description: 'Account ID for Cloudflare Pages (from the Workers & Pages section of the dashboard)'
required: true
cloudflare-project-name:
description: 'Name of your Cloudflare Pages project (from the Workers & Pages section of the dashboard)'
required: true
sleep-seconds:
description: 'Time to sleep before starting to poll deployment status (in seconds)'
required: false
default: "300"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the API limits? Is there a risk we'll hit those if we reduce the polling / wait times? 5 minutes initial wait feels long, assuming build times are similar to Vercel, can we wait, say < 30 sec? And also poll every 10 sec or so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's 1200 requests per 5 minutes. So assuming the user's token is only being used by us, polling once a minute would mean we can be waiting on 240 concurrent builds without hitting the limit. It might be safe to reduce that, but we might break in cases of tools like dependabot opening a load of PRs at once. Still, halving to 30 seconds is probably safe, I'll do that.

deployment-poll-seconds:
description: 'Time to wait between API calls to poll for the deployment to be ready (in seconds)'
required: false
default: "60"
wait-till-ready-seconds:
description: 'Maximum time to wait for the deployment to be ready (in seconds)'
required: false
default: "3600"
runs:
using: "composite"
steps:
- name: Sleep a bit to wait for the deployment to exist
if: ${{ inputs.sleep-time != '0' }}
shell: bash
run: sleep ${{ inputs.sleep-time }}
- name: Wait for deployment to be ready and get URL
shell: bash
id: get-url
run: |
STATUS="unknown"
SLEPT=0
while [[ "$STATUS" != "success" ]]; do
echo "Checking deployment status..."
STATUS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${{ inputs.cloudflare-account-id }}/pages/projects/${{ inputs.cloudflare-project-name }}/deployments" -H "Authorization: Bearer ${{ inputs.cloudflare-api-token }}" -H "Content-Type:application/json" | jq -c 'first(.result[] | select(.deployment_trigger.metadata.commit_hash == "${{ github.sha }}") | .latest_stage.status)' --raw-output | tr -d '\n')
if [[ "$STATUS" != "success" ]]; then
if [[ $SLEPT -gt ${{ inputs.wait-till-ready-seconds }} ]]; then
echo "Deployment is still not ready, failing..."
exit 1
fi
echo "Deployment is not ready yet, sleeping..."
sleep ${{ inputs.deployment-poll-seconds }}
SLEPT=$((SLEPT+${{ inputs.deployment-poll-seconds }}))
fi
done
echo "Deployment is ready!"
echo "url=`curl -s -X GET "https://api.cloudflare.com/client/v4/accounts/${{ inputs.cloudflare-account-id }}/pages/projects/${{ inputs.cloudflare-project-name }}/deployments" -H "Authorization: Bearer ${{ inputs.cloudflare-api-token }}" -H "Content-Type:application/json" | jq -c 'first(.result[] | select(.deployment_trigger.metadata.commit_hash == "${{ github.sha }}") | .url)' --raw-output | tr -d '\n'`" >> $GITHUB_OUTPUT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does cloudflare-project-name (or any other part) need to be URL encoded?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the project name is alphanumeric plus - which doesn't need to be encoded. The others are all just alphanumeric.

- name: Create GitHub deployment from Cloudflare Pages deployment
uses: altinukshini/deployment-action@releases/v1
with:
token: "${{ inputs.github-token }}"
target_url: "${{ steps.get-url.outputs.url }}"
initial_status: "success"
environment: "Meticulous"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does CF Pages return environment name? If so can we use that from there? If not should we give this deployment some non-Meticulous specific name which mentions CF?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, let's do Cloudfront Pages: << name there >>.

Loading