Skip to content
Merged
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
74 changes: 74 additions & 0 deletions .github/workflows/valian-fireway.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: fireway migrate

on:
workflow_call:
inputs:
workload-identity-project-number:
description: the GCP project number used for Workload Identity Federation
required: true
type: string
gcp-project-id:
description: The firebase project environment used for the deployment
required: true
type: string
gcp-service-account:
description: the email address of the service account
required: true
type: string
working-directory:
description: The working directory of the firebase project
required: false
type: string
default: functions
dry-run:
description: run migrations in dry-run mode
type: boolean
required: false
default: false
slack-channel-id:
description: Slack channel id to send alerts to
type: string
required: false
Comment on lines +3 to +31
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Expose SLACK_BOT_TOKEN in workflow_call secrets.

The Slack step (Line 73) reads secrets.SLACK_BOT_TOKEN, but reusable workflows must explicitly declare secrets; otherwise the token is unavailable and the action will fail or no-op.

✅ Proposed fix
 on:
   workflow_call:
     inputs:
       workload-identity-project-number:
         description: the GCP project number used for Workload Identity Federation
         required: true
         type: string
@@
       slack-channel-id:
         description: Slack channel id to send alerts to
         type: string
         required: false
+    secrets:
+      SLACK_BOT_TOKEN:
+        required: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
workflow_call:
inputs:
workload-identity-project-number:
description: the GCP project number used for Workload Identity Federation
required: true
type: string
gcp-project-id:
description: The firebase project environment used for the deployment
required: true
type: string
gcp-service-account:
description: the email address of the service account
required: true
type: string
working-directory:
description: The working directory of the firebase project
required: false
type: string
default: functions
dry-run:
description: run migrations in dry-run mode
type: boolean
required: false
default: false
slack-channel-id:
description: Slack channel id to send alerts to
type: string
required: false
on:
workflow_call:
inputs:
workload-identity-project-number:
description: the GCP project number used for Workload Identity Federation
required: true
type: string
gcp-project-id:
description: The firebase project environment used for the deployment
required: true
type: string
gcp-service-account:
description: the email address of the service account
required: true
type: string
working-directory:
description: The working directory of the firebase project
required: false
type: string
default: functions
dry-run:
description: run migrations in dry-run mode
type: boolean
required: false
default: false
slack-channel-id:
description: Slack channel id to send alerts to
type: string
required: false
secrets:
SLACK_BOT_TOKEN:
required: false
🤖 Prompt for AI Agents
In @.github/workflows/valian-fireway.yml around lines 3 - 31, The reusable
workflow does not declare the SLACK_BOT_TOKEN secret required by the Slack step
(it reads secrets.SLACK_BOT_TOKEN), so add a workflow_call secrets declaration
for SLACK_BOT_TOKEN; specifically, under workflow_call add a secrets: block with
SLACK_BOT_TOKEN: required: true so the secret is passed into the workflow when
invoked.


jobs:
fireway:
name: fireway
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
concurrency:
group: fireway-migrate-${{ inputs.gcp-project-id }}
steps:
- uses: actions/checkout@v6
- name: setup pnpm
uses: valian-ca/github-workflows/.github/actions/setup-pnpm@main
- uses: valian-ca/github-workflows/.github/actions/gcp-github-auth@main
with:
workload-identity-project-number: ${{ inputs.workload-identity-project-number }}
gcp-service-account: ${{ inputs.gcp-service-account }}

- uses: google-github-actions/setup-gcloud@v3
with:
project_id: ${{ inputs.gcp-project-id }}
Comment on lines +43 to +53
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

actions/checkout v6 latest stable version GitHub Actions

💡 Result:

Latest stable release for actions/checkout v6 is v6.0.1 (released Dec 2, 2025). [1]

Sources:
[1] actions/checkout releases (GitHub).


🌐 Web query:

google-github-actions setup-gcloud latest stable version documentation

💡 Result:

The action's current stable major release is v3 (latest patch v3.0.1). Pin like:

  • uses: google-github-actions/setup-gcloud@v3
    or pin exact release:
  • uses: google-github-actions/setup-gcloud@v3.0.1

Docs (inputs, default version behavior, version constraints, Workload Identity requirements): README. [1][2][3]

Sources:

  • README / usage & inputs. [1]
  • Releases (v3.0.1 release). [2]
  • GitHub Marketplace listing (latest published). [3]

🌐 Web query:

GitHub Actions best practices pinning commit SHA vs tags security

💡 Result:

Short answer

  • Prefer pinning third‑party actions to a full-length commit SHA (immutable) for security; tags/branches are mutable and can be moved to malicious code. [1][3]

When tags may be acceptable

  • Tag (or semver) pins are OK only for actions/releases that are provably immutable (GitHub immutable releases / “immutable actions”) or when you fully trust and control the action’s repo/author. Even then prefer a process that validates immutability. [2][5]

Practical best practices

  1. Pin to full commit SHAs for third‑party actions by default. This is the only current guarantee of immutability. [1][3]
  2. Enforce SHA pinning via enterprise/org/repo allowed‑actions policy when possible. [2][3]
  3. Automate updates (Dependabot, Renovate, pinning bots) so you can review and merge SHA bumps rather than using mutable tags. [3][8]
  4. Prefer Verified creators and audit action source code (or use actions from your org). Avoid “unpinnable” actions that pull remote code at runtime. [1][3]
  5. Block known‑bad actions and use policy blocklists, secrets least privilege, and other workflow hardening (reuse rules, OSSF/scorecards). [2][3]

References
[1] GitHub Docs — Secure use reference / pin actions to full-length commit SHA.
[2] GitHub Changelog — allowed actions policy and SHA pinning enforcement (immutable releases roadmap).
[3] GitHub Well‑Architected / Actions security — pin SHAs, avoid unpinnable actions, enforce policies.
[5] StepSecurity reporting on immutable actions and policy options.
[8] Guidance on automating SHA pin updates (Dependabot/renovate/pinning tools).


Pin GitHub Actions to commit SHAs to harden supply-chain security.

Using mutable references like @main and major version tags (e.g., @v3) introduces supply-chain risk, as tags can be reassigned to different commits. GitHub's official security guidance recommends pinning all actions to full commit SHAs for immutability. While actions/checkout@v6 (v6.0.1) and google-github-actions/setup-gcloud@v3 (v3.0.1) are valid and documented, they should be pinned to specific commit SHAs instead of version tags.

For internal actions in valian-ca/github-workflows (currently pinned to @main), also switch to commit SHAs to enforce consistency and prevent accidental code changes.

Consider automating SHA pin updates using Dependabot or Renovate to keep actions current while maintaining security.

🤖 Prompt for AI Agents
In @.github/workflows/valian-fireway.yml around lines 43 - 53, The workflow is
using mutable action refs (actions/checkout@v6,
valian-ca/github-workflows/.github/actions/setup-pnpm@main,
valian-ca/github-workflows/.github/actions/gcp-github-auth@main,
google-github-actions/setup-gcloud@v3); replace each mutable tag with the
corresponding full commit SHA for those actions so they are pinned immutably,
e.g., update the uses entries for actions/checkout, the two valian-ca internal
actions, and google-github-actions/setup-gcloud to reference their specific
commit SHAs (and consider adding Dependabot/Renovate config to automate future
SHA updates).


- name: configure firebase environment
run: npx firebase use ${{ inputs.gcp-project-id }}
working-directory: ${{ inputs.working-directory }}

- name: run migrations ${{ inputs.dry-run && 'in dry run mode' || '' }}
env:
GCLOUD_PROJECT: ${{ inputs.gcp-project-id }}
run: npx @valian/fireway migrate ${{ inputs.dry-run && '--dryRun' || '' }}
working-directory: ${{ inputs.working-directory }}

- name: notify Slack of failure
id: slack
if: ${{ !success() && inputs.slack-channel-id != '' }}
uses: valian-ca/github-workflows/.github/actions/slack-alert@main
with:
message: fireway migrate ${{ inputs.gcp-project-id }} error
mrkdwn: |
:warning: fireway migrate *${{ inputs.gcp-project-id }}* (`${{ job.status }}`)
token: ${{ secrets.SLACK_BOT_TOKEN }}
Comment on lines +65 to +73
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

GitHub Actions success() failure() cancelled() step if condition semantics

💡 Result:

Short summary of semantics and gotchas

  • Default: an omitted if on a job or step is treated as if: success() (i.e., run only when prior required steps/jobs succeeded). [1][2]

  • success(): true when all previous steps (in the same job) or all needed jobs (for job-level if with needs:) succeeded. Use to run only on overall success. [2][3]

  • failure(): true when any previous step (or any needed job in a dependency chain) has failed. Note: using failure() in an if overrides the default success() status check. You can combine it with extra predicates (e.g., failure() && steps.foo.conclusion == 'failure'). [2][3]

  • cancelled(): true when the workflow or job was cancelled. Use to run steps/jobs only when cancellation occurred. [2][3]

  • always(): returns true even if cancelled; it forces execution unconditionally (including during cancellation). Because always() still runs when a workflow is cancelled, GitHub recommends using if: ${{ !cancelled() }} when you want "always except when cancelled". [2][4]

  • Evaluation during cancellation: when a workflow is cancelled GitHub re-evaluates job-level and then unfinished step-level if conditions. Jobs/steps whose if evaluates true may continue; others get cancelled. Runners send SIGINT/SIGTERM to canceled steps and eventually kill them. [4]

  • needs: interaction: job-level status-check functions (success/failure/cancelled) consider the status of needed jobs (ancestors). A job without an explicit status-check function behaves like if: success() && (your other conditions). failure() returns true if any ancestor job failed. Skipped ancestors can cause a dependent job to be skipped under success(). [3][5]

Practical rules

  • Use explicit status functions when you need behaviour different from the default.
  • To run cleanup on failure or cancellation, prefer separate steps with if: ${{ failure() || cancelled() }} or use an always() step but guard with !cancelled() if you must avoid running during cancellation. [2][4]
  • Remember YAML quoting rules: use ${{ }} (or quote) when expressions start with !. [6]

Sources
[1] GitHub Docs — Expressions / Evaluate expressions (status functions).
[2] GitHub Docs — Evaluate expressions in workflows and actions (success/failure/cancelled/always examples).
[3] GitHub Docs — Workflow syntax for GitHub Actions (jobs.steps.if and default behavior).
[4] GitHub Docs — Workflow cancellation reference (how if is re-evaluated during cancel and runner termination behavior).
[5] Community tests and examples showing needs/status interactions.

If you want, I can produce a few minimal workflow examples that demonstrate each case.


🌐 Web query:

GitHub Actions secrets in if condition expression whether allowed

💡 Result:

Short answer: No — GitHub Actions does not allow directly referencing secrets in an if: expression. Use a non-secret value (env var, step output) derived from the secret and test that instead. [1][2]

Why and alternatives:

  • Official docs: "Secrets cannot be directly referenced in if: conditionals." Recommend setting secrets as job-level environment variables or producing a non-secret result and using that in if. [1]
  • Common workaround: read/inspect the secret in a step (or set an env at job/step level) and emit a boolean output or env var, then use that output/env in later if: checks. (Examples and community discussion). [2][3]

References:

  • GitHub Docs — Using secrets in GitHub Actions. [1]
  • GitHub Docs — Expressions / if conditionals. [2]
  • Community discussion / workaround examples. [3]

Use failure() instead of !success() to avoid Slack alerts on workflow cancellations.

When a run is cancelled, !success() evaluates to true, causing unnecessary Slack notifications. Use failure() to alert only on actual failures. Note: secrets cannot be checked in if conditions in GitHub Actions; if the token is missing, the step will fail. If you want to guard against that, set a job-level environment variable from the secret and check that instead.

✅ Suggested condition
-        if: ${{ !success() && inputs.slack-channel-id != '' }}
+        if: ${{ failure() && inputs.slack-channel-id != '' }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: notify Slack of failure
id: slack
if: ${{ !success() && inputs.slack-channel-id != '' }}
uses: valian-ca/github-workflows/.github/actions/slack-alert@main
with:
message: fireway migrate ${{ inputs.gcp-project-id }} error
mrkdwn: |
:warning: fireway migrate *${{ inputs.gcp-project-id }}* (`${{ job.status }}`)
token: ${{ secrets.SLACK_BOT_TOKEN }}
- name: notify Slack of failure
id: slack
if: ${{ failure() && inputs.slack-channel-id != '' }}
uses: valian-ca/github-workflows/.github/actions/slack-alert@main
with:
message: fireway migrate ${{ inputs.gcp-project-id }} error
mrkdwn: |
:warning: fireway migrate *${{ inputs.gcp-project-id }}* (`${{ job.status }}`)
token: ${{ secrets.SLACK_BOT_TOKEN }}
🤖 Prompt for AI Agents
In @.github/workflows/valian-fireway.yml around lines 65 - 73, Change the Slack
notification step condition from using the negated success check to GitHub
Actions' failure() so cancellations don't trigger alerts: update the step with
name "notify Slack of failure" (id "slack") to use if: failure(); also note that
secrets can't be directly checked in if conditions—if you need to guard against
a missing SLACK_BOT_TOKEN, populate a job-level env var from the secret and
check that env var in the condition instead.

channel: ${{ inputs.slack-channel-id }}