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
99 changes: 58 additions & 41 deletions .github/workflows/api-preview.yml
Original file line number Diff line number Diff line change
@@ -1,63 +1,80 @@
name: Fly Preview API server
on:
pull_request:
types: [opened, reopened, synchronize, closed]
paths:
- "apps/server/**"
- "packages/db/**"
- "packages/emails/**"
- "packages/regions/**"
- "packages/tsconfig/**"
- "packages/utils/**"
- "packages/upstash/**"
- "packages/proto/**"
workflow_dispatch:
inputs:
action:
description: "Action to perform"
required: true
type: choice
options:
- deploy
- destroy

Comment on lines 2 to +12
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Switching the trigger from pull_request to workflow_dispatch means preview apps will no longer deploy/destroy automatically on PR open/sync/close (and path filters no longer apply). If the goal is still PR previews, consider keeping pull_request (optionally alongside workflow_dispatch) so PR lifecycle events continue to manage the preview environment.

Copilot uses AI. Check for mistakes.
permissions:
contents: read
deployments: write

env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
# Set these to your Fly.io organization and preferred region.
FLY_REGION: ams
FLY_ORG: openstatus
APP_NAME: openstatus-api-preview-${{ github.ref_name }}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

APP_NAME is derived from github.ref_name, which can contain characters Fly app names don't allow (e.g., /, ., uppercase) and can also exceed length limits. This can cause flyctl apps create/deploy to fail for common branch names like feature/foo. Consider generating a sanitized, lowercased, length-limited app name in a step (writing to $GITHUB_ENV) or accepting an explicit app_name input.

Suggested change
APP_NAME: openstatus-api-preview-${{ github.ref_name }}
APP_NAME: ${{ format('openstatus-api-preview-{0}', substr(toLower(replace(replace(github.ref_name, '/', '-'), '.', '-')), 0, 40)) }}

Copilot uses AI. Check for mistakes.

jobs:
review_app:
deploy:
if: ${{ github.event.inputs.action == 'deploy' }}
runs-on: depot-ubuntu-24.04-4
timeout-minutes: 15
outputs:
url: ${{ steps.deploy.outputs.url }}
# Only run one deployment at a time per PR.
concurrency:
group: pr-${{ github.event.number }}

# Deploying apps with this "review" environment allows the URL for the app to be displayed in the PR UI.
# Feel free to change the name of this environment.
group: api-preview-${{ github.ref_name }}
environment:
name: pr-${{ github.event.number }} # The script in the `deploy` sets the URL output for each review app.
url: ${{ steps.deploy.outputs.url }}
name: api-preview-${{ github.ref_name }}
url: https://${{ env.APP_NAME }}.fly.dev
steps:
- name: Get code
uses: actions/checkout@v4

- name: Deploy PR app to Fly.io
id: deploy
uses: superfly/fly-pr-review-apps@1.2.1
with:
config: apps/server/fly.toml
vmsize: shared-cpu-1x
name: openstatus-api-pr-${{ github.event.number }}
secrets: |
DATABASE_URL=${{ secrets.STAGING_DB_URL }}
DATABASE_AUTH_TOKEN=${{ env.STAGING_DB_AUTH_TOKEN }}
RESEND_API_KEY=${{ secrets.STAGING_RESEND_API_KEY }}
UPSTASH_REDIS_REST_URL=test
UPSTASH_REDIS_REST_TOKEN=test
GCP_PROJECT_ID=test
NEXT_PUBLIC_OPENPANEL_CLIENT_ID=test
OPENPANEL_CLIENT_SECRET=test
- name: Setup Fly.io CLI
uses: superfly/flyctl-actions/setup-flyctl@master

Comment on lines +37 to +39
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Using superfly/flyctl-actions/setup-flyctl@master pins to a moving branch, which is a supply-chain risk and can cause unexpected breaks if master changes. Prefer pinning to a tagged release or a specific commit SHA.

Copilot uses AI. Check for mistakes.
- name: Create app if not exists
run: flyctl apps create ${{ env.APP_NAME }} --org ${{ env.FLY_ORG }} || true
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

flyctl apps create ... || true will also ignore real failures (e.g., invalid app name, auth/org issues), making the root cause harder to diagnose and potentially continuing to later steps with a misconfigured app. Consider handling only the "already exists" case explicitly (or checking existence first) and failing on other errors.

Suggested change
run: flyctl apps create ${{ env.APP_NAME }} --org ${{ env.FLY_ORG }} || true
run: |
if ! flyctl apps show "$APP_NAME" >/dev/null 2>&1; then
flyctl apps create "$APP_NAME" --org "$FLY_ORG"
fi

Copilot uses AI. Check for mistakes.

- name: Set secrets
run: |
flyctl secrets set \
DATABASE_URL="${{ secrets.STAGING_DB_URL }}" \
DATABASE_AUTH_TOKEN="${{ secrets.STAGING_DB_AUTH_TOKEN }}" \
RESEND_API_KEY="${{ secrets.STAGING_RESEND_API_KEY }}" \
UPSTASH_REDIS_REST_URL=test \
UPSTASH_REDIS_REST_TOKEN=test \
GCP_PROJECT_ID=test \
NEXT_PUBLIC_OPENPANEL_CLIENT_ID=test \
OPENPANEL_CLIENT_SECRET=test \
--app ${{ env.APP_NAME }}

- name: Deploy to Fly.io
run: |
flyctl deploy \
--config apps/server/fly.toml \
--app ${{ env.APP_NAME }} \
--region ${{ env.FLY_REGION }} \
--vm-size shared-cpu-1x \
--yes

destroy:
if: ${{ github.event.inputs.action == 'destroy' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Setup Fly.io CLI
uses: superfly/flyctl-actions/setup-flyctl@master

- name: Destroy app
run: flyctl apps destroy ${{ env.APP_NAME }} --yes || true

- name: Clean up GitHub environment
uses: strumwolf/delete-deployment-environment@v2
if: ${{ github.event.action == 'closed' }}
with:
# ⚠️ The provided token needs permission for admin write:org
token: ${{ secrets.GITHUB_TOKEN }}
environment: pr-${{ github.event.number }}
environment: api-preview-${{ github.ref_name }}
Comment on lines +73 to +80
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

flyctl apps destroy ... || true masks failures (e.g., permission issues), and the workflow will still delete the GitHub environment afterwards, which can leave orphaned Fly apps while removing the tracking environment. Consider removing || true, or at least conditionally running the environment cleanup only when the destroy succeeded.

Copilot uses AI. Check for mistakes.
93 changes: 56 additions & 37 deletions .github/workflows/workflow-preview.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,78 @@
name: Fly Preview Workflows
on:
pull_request:
types: [opened, reopened, synchronize, closed]
paths:
- "apps/workflows/**"
- "packages/db/**"
- "packages/emails/**"
- "packages/utils/**"
- "packages/notifications/**"
- "packages/tsconfig/**"
workflow_dispatch:
inputs:
action:
description: "Action to perform"
required: true
type: choice
options:
- deploy
- destroy
Comment on lines 2 to +11
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Switching the trigger from pull_request to workflow_dispatch means preview apps will no longer deploy/destroy automatically on PR open/sync/close (and path filters no longer apply). If the goal is still PR previews, consider keeping pull_request (optionally alongside workflow_dispatch) so PR lifecycle events continue to manage the preview environment.

Copilot uses AI. Check for mistakes.

permissions:
contents: read
deployments: write

env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
# Set these to your Fly.io organization and preferred region.
FLY_REGION: ams
FLY_ORG: openstatus
APP_NAME: openstatus-workflows-preview-${{ github.ref_name }}

Comment on lines 17 to 22
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

APP_NAME is derived from github.ref_name, which can contain characters Fly app names don't allow (e.g., /, ., uppercase) and can also exceed length limits. This can cause flyctl apps create/deploy to fail for common branch names like feature/foo. Consider generating a sanitized, lowercased, length-limited app name in a step (writing to $GITHUB_ENV) or accepting an explicit app_name input.

Copilot uses AI. Check for mistakes.
jobs:
review_app:
deploy:
if: ${{ github.event.inputs.action == 'deploy' }}
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
url: ${{ steps.deploy.outputs.url }}
# Only run one deployment at a time per PR.
concurrency:
group: pr-${{ github.event.number }}

# Deploying apps with this "review" environment allows the URL for the app to be displayed in the PR UI.
# Feel free to change the name of this environment.
group: workflows-preview-${{ github.ref_name }}
environment:
name: pr-${{ github.event.number }} # The script in the `deploy` sets the URL output for each review app.
url: ${{ steps.deploy.outputs.url }}
name: workflows-preview-${{ github.ref_name }}
url: https://${{ env.APP_NAME }}.fly.dev
steps:
- name: Get code
uses: actions/checkout@v4

- name: Deploy PR app to Fly.io
id: deploy
uses: superfly/fly-pr-review-apps@1.2.1
with:
config: apps/workflows/fly.toml
vmsize: shared-cpu-1x
name: openstatus-workflows-pr-${{ github.event.number }}
secrets: |
DATABASE_URL=${{ secrets.STAGING_DB_URL }}
DATABASE_AUTH_TOKEN=${{ env.STAGING_DB_AUTH_TOKEN }}
RESEND_API_KEY=${{ secrets.STAGING_RESEND_API_KEY }}
UPSTASH_REDIS_REST_URL=test
UPSTASH_REDIS_REST_TOKEN=test
GCP_PROJECT_ID=test
- name: Setup Fly.io CLI
uses: superfly/flyctl-actions/setup-flyctl@master

Comment on lines +37 to +39
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Using superfly/flyctl-actions/setup-flyctl@master pins to a moving branch, which is a supply-chain risk and can cause unexpected breaks if master changes. Prefer pinning to a tagged release or a specific commit SHA.

Copilot uses AI. Check for mistakes.
- name: Create app if not exists
run: flyctl apps create ${{ env.APP_NAME }} --org ${{ env.FLY_ORG }} || true

Comment on lines +40 to +42
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

flyctl apps create ... || true will also ignore real failures (e.g., invalid app name, auth/org issues), making the root cause harder to diagnose and potentially continuing to later steps with a misconfigured app. Consider handling only the "already exists" case explicitly (or checking existence first) and failing on other errors.

Copilot uses AI. Check for mistakes.
- name: Set secrets
run: |
flyctl secrets set \
DATABASE_URL="${{ secrets.STAGING_DB_URL }}" \
DATABASE_AUTH_TOKEN="${{ secrets.STAGING_DB_AUTH_TOKEN }}" \
RESEND_API_KEY="${{ secrets.STAGING_RESEND_API_KEY }}" \
UPSTASH_REDIS_REST_URL=test \
UPSTASH_REDIS_REST_TOKEN=test \
GCP_PROJECT_ID=test \
--app ${{ env.APP_NAME }}

- name: Deploy to Fly.io
run: |
flyctl deploy \
--config apps/workflows/fly.toml \
--app ${{ env.APP_NAME }} \
--region ${{ env.FLY_REGION }} \
--vm-size shared-cpu-1x \
--yes

destroy:
Comment on lines +25 to +63

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 8 days ago

In general, the fix is to explicitly declare a permissions block for the workflow or per job so that the GITHUB_TOKEN is restricted to the minimal set of scopes required. For this workflow, the deploy job needs to read repository contents for actions/checkout@v4, and the destroy job needs to clean up a GitHub environment using strumwolf/delete-deployment-environment@v2, which typically requires deployments: write but not broader write access.

The best fix, without changing existing functionality, is to add a top‑level permissions block that applies to the whole workflow with:

  • contents: read to allow checkout,
  • deployments: write to allow deleting the deployment environment,
    and nothing else. This documents the needed permissions and prevents the token from having unnecessary write scopes like contents: write, issues: write, or pull-requests: write. Concretely, in .github/workflows/workflow-preview.yml, insert a permissions block after the on: section (after line 11/12) so it applies to all jobs. No additional imports or methods are needed since this is just YAML configuration.
Suggested changeset 1
.github/workflows/workflow-preview.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/workflow-preview.yml b/.github/workflows/workflow-preview.yml
--- a/.github/workflows/workflow-preview.yml
+++ b/.github/workflows/workflow-preview.yml
@@ -10,6 +10,10 @@
           - deploy
           - destroy
 
+permissions:
+  contents: read
+  deployments: write
+
 env:
     FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
     FLY_REGION: ams
EOF
@@ -10,6 +10,10 @@
- deploy
- destroy

permissions:
contents: read
deployments: write

env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
FLY_REGION: ams
Copilot is powered by AI and may make mistakes. Always verify output.
@thibaultleouay thibaultleouay committed this autofix suggestion 8 days ago.
if: ${{ github.event.inputs.action == 'destroy' }}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Setup Fly.io CLI
uses: superfly/flyctl-actions/setup-flyctl@master

- name: Destroy app
run: flyctl apps destroy ${{ env.APP_NAME }} --yes || true

- name: Clean up GitHub environment
uses: strumwolf/delete-deployment-environment@v2
if: ${{ github.event.action == 'closed' }}
with:
# ⚠️ The provided token needs permission for admin write:org
token: ${{ secrets.GITHUB_TOKEN }}
environment: pr-${{ github.event.number }}
environment: workflows-preview-${{ github.ref_name }}
Comment on lines +64 to +78

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI 8 days ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

Comment on lines +71 to +78
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

flyctl apps destroy ... || true masks failures (e.g., permission issues), and the workflow will still delete the GitHub environment afterwards, which can leave orphaned Fly apps while removing the tracking environment. Consider removing || true, or at least conditionally running the environment cleanup only when the destroy succeeded.

Copilot uses AI. Check for mistakes.
Loading