refactor: deduplicate CI workflows and fix double triggers#138
refactor: deduplicate CI workflows and fix double triggers#138
Conversation
Extract reusable workflows (_build-backend.yml, _build-ext.yml) to eliminate duplicated build/deploy logic across dev/stg/prd. Remove `push: tags: v*` trigger from stg/prd backend workflows to prevent double builds (bump-version already dispatches via repository_dispatch). Delete the no-op build-ext-dev.yml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR refactors GitHub Actions CI/CD by extracting duplicated backend and Chrome extension build/deploy logic into reusable workflows, and adjusts triggers to avoid double builds on tag pushes (relying on repository_dispatch from bump-version.yml for stg/prd).
Changes:
- Added reusable workflows:
_build-backend.ymland_build-ext.yml. - Updated dev/stg/prd backend workflows and stg/prd extension workflows to call the reusable workflows.
- Removed
push: tags: v*triggers from stg/prd backend workflows and deleted the unusedbuild-ext-dev.yml.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/_build-backend.yml | New reusable workflow that builds/pushes backend image and deploys manifests for dev/stg/prd. |
| .github/workflows/_build-ext.yml | New reusable workflow that builds and uploads the Chrome extension for stg/prd. |
| .github/workflows/build-backend-dev.yml | Refactored to call _build-backend.yml for dev branch pushes. |
| .github/workflows/build-backend-stg.yml | Refactored to call _build-backend.yml for repository_dispatch (stg). |
| .github/workflows/build-backend-prd.yml | Refactored to call _build-backend.yml for repository_dispatch (prd). |
| .github/workflows/build-ext-stg.yml | Refactored to call _build-ext.yml for repository_dispatch (stg). |
| .github/workflows/build-ext-prd.yml | Refactored to call _build-ext.yml for repository_dispatch (prd). |
| .github/workflows/build-ext-dev.yml | Deleted no-op dev extension workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| zip_file: 'dist.zip' | ||
| build-and-publish: | ||
| uses: ./.github/workflows/_build-ext.yml | ||
| secrets: inherit |
There was a problem hiding this comment.
Using secrets: inherit passes all repository/environment secrets into the called workflow, which is broader than needed for the extension build/publish. After declaring required secrets in _build-ext.yml, pass only the needed secrets explicitly from this caller.
| secrets: inherit | |
| secrets: | |
| CHROME_WEBSTORE_CLIENT_ID: ${{ secrets.CHROME_WEBSTORE_CLIENT_ID }} | |
| CHROME_WEBSTORE_CLIENT_SECRET: ${{ secrets.CHROME_WEBSTORE_CLIENT_SECRET }} | |
| CHROME_WEBSTORE_REFRESH_TOKEN: ${{ secrets.CHROME_WEBSTORE_REFRESH_TOKEN }} |
| type: string # staging, main | ||
| extension_id: | ||
| required: true | ||
| type: string |
There was a problem hiding this comment.
_build-ext.yml is a reusable workflow (workflow_call) but it doesn’t declare any on.workflow_call.secrets. In reusable workflows, only declared secrets are made available to the secrets.* context, so the Chrome Web Store and Grafana secrets referenced later may be empty at runtime. Declare the required secrets under on.workflow_call.secrets (and consider passing only those from callers instead of secrets: inherit).
| type: string | |
| type: string | |
| secrets: | |
| GRAFANA_API_KEY: | |
| required: true | |
| CHROME_EXT_CLIENT_ID: | |
| required: true | |
| CHROME_EXT_CLIENT_SECRET: | |
| required: true | |
| CHROME_EXT_REFRESH_TOKEN: | |
| required: true |
| type: string # development, staging, main | ||
| version_tag: | ||
| required: true | ||
| type: string # e.g. "development" or "v2.1.3" |
There was a problem hiding this comment.
_build-backend.yml is a reusable workflow (workflow_call) but it doesn’t declare any on.workflow_call.secrets. Secrets like GH_PAT and the environment-specific *_DEV/_STG/_PRD values referenced in env: will not be available unless they’re declared for workflow_call. Add a secrets: block under on.workflow_call listing all secrets this workflow reads.
| type: string # e.g. "development" or "v2.1.3" | |
| type: string # e.g. "development" or "v2.1.3" | |
| secrets: | |
| GH_PAT: | |
| required: true |
| OPENAI_BASE_URL: ${{ inputs.environment == 'dev' && secrets.OPENAI_BASE_URL_DEV || inputs.environment == 'stg' && secrets.OPENAI_BASE_URL_STG || secrets.OPENAI_BASE_URL_PRD }} | ||
| OPENAI_API_KEY: ${{ inputs.environment == 'dev' && secrets.OPENAI_API_KEY_DEV || inputs.environment == 'stg' && secrets.OPENAI_API_KEY_STG || secrets.OPENAI_API_KEY_PRD }} | ||
| INFERENCE_BASE_URL: ${{ inputs.environment == 'dev' && secrets.INFERENCE_BASE_URL_DEV || inputs.environment == 'stg' && secrets.INFERENCE_BASE_URL_STG || secrets.INFERENCE_BASE_URL_PRD }} | ||
| INFERENCE_API_KEY: ${{ inputs.environment == 'dev' && secrets.INFERENCE_API_KEY_DEV || inputs.environment == 'stg' && secrets.INFERENCE_API_KEY_STG || secrets.INFERENCE_API_KEY_PRD }} | ||
| MCP_BASIC_KEY: ${{ inputs.environment == 'dev' && secrets.MCP_BASIC_KEY_DEV || inputs.environment == 'stg' && secrets.MCP_BASIC_KEY_STG || secrets.MCP_BASIC_KEY_PRD }} | ||
| MCP_PAPERSCORE_KEY: ${{ inputs.environment == 'dev' && secrets.MCP_PAPERSCORE_KEY_DEV || inputs.environment == 'stg' && secrets.MCP_PAPERSCORE_KEY_STG || secrets.MCP_PAPERSCORE_KEY_PRD }} | ||
| XTRAMCP_OPENAI_BASE_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENAI_BASE_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENAI_BASE_URL_STG || secrets.XTRAMCP_OPENAI_BASE_URL_PRD }} | ||
| XTRAMCP_OPENAI_API_KEY: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENAI_API_KEY_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENAI_API_KEY_STG || secrets.XTRAMCP_OPENAI_API_KEY_PRD }} | ||
| XTRAMCP_OPENREVIEW_BASE_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_BASE_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_BASE_URL_STG || secrets.XTRAMCP_OPENREVIEW_BASE_URL_PRD }} | ||
| XTRAMCP_OPENREVIEW_USERNAME: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_USERNAME_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_USERNAME_STG || secrets.XTRAMCP_OPENREVIEW_USERNAME_PRD }} | ||
| XTRAMCP_OPENREVIEW_PASSWORD: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_PASSWORD_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_PASSWORD_STG || secrets.XTRAMCP_OPENREVIEW_PASSWORD_PRD }} | ||
| XTRAMCP_CROSSREF_EMAIL_ADDRESS: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG || secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_PRD }} | ||
| XTRAMCP_DOI_EMAIL_ADDRESS: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_DOI_EMAIL_ADDRESS_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_DOI_EMAIL_ADDRESS_STG || secrets.XTRAMCP_DOI_EMAIL_ADDRESS_PRD }} | ||
| XTRAMCP_ACL_METADATA_DB_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_ACL_METADATA_DB_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_ACL_METADATA_DB_URL_STG || secrets.XTRAMCP_ACL_METADATA_DB_URL_PRD }} | ||
| XTRAMCP_ARXIV_METADATA_DB_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_ARXIV_METADATA_DB_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_ARXIV_METADATA_DB_URL_STG || secrets.XTRAMCP_ARXIV_METADATA_DB_URL_PRD }} | ||
| XTRAMCP_MONGO_URI: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_MONGO_URI_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_MONGO_URI_STG || secrets.XTRAMCP_MONGO_URI_PRD }} | ||
| MONGO_URI: ${{ inputs.environment == 'dev' && secrets.MONGO_URI_DEV || inputs.environment == 'stg' && secrets.MONGO_URI_STG || secrets.MONGO_URI_PRD }} | ||
| GHCR_DOCKER_CONFIG: ${{ inputs.environment == 'dev' && secrets.GHCR_DOCKER_CONFIG_DEV || inputs.environment == 'stg' && secrets.GHCR_DOCKER_CONFIG_STG || secrets.GHCR_DOCKER_CONFIG_PRD }} | ||
| CLOUDFLARE_TUNNEL_TOKEN: ${{ inputs.environment == 'dev' && secrets.CLOUDFLARE_TUNNEL_TOKEN_DEV || inputs.environment == 'stg' && secrets.CLOUDFLARE_TUNNEL_TOKEN_STG || secrets.CLOUDFLARE_TUNNEL_TOKEN_PRD }} | ||
| run: | |
There was a problem hiding this comment.
The chained &&/|| expressions selecting secrets will silently fall back to the PRD secret when inputs.environment isn’t exactly dev or stg (and can also fall through if a selected secret is an empty string). Add an explicit validation/branching step (e.g., a shell case that sets env vars and errors on unknown values) so a typo can’t accidentally select production configuration.
| OPENAI_BASE_URL: ${{ inputs.environment == 'dev' && secrets.OPENAI_BASE_URL_DEV || inputs.environment == 'stg' && secrets.OPENAI_BASE_URL_STG || secrets.OPENAI_BASE_URL_PRD }} | |
| OPENAI_API_KEY: ${{ inputs.environment == 'dev' && secrets.OPENAI_API_KEY_DEV || inputs.environment == 'stg' && secrets.OPENAI_API_KEY_STG || secrets.OPENAI_API_KEY_PRD }} | |
| INFERENCE_BASE_URL: ${{ inputs.environment == 'dev' && secrets.INFERENCE_BASE_URL_DEV || inputs.environment == 'stg' && secrets.INFERENCE_BASE_URL_STG || secrets.INFERENCE_BASE_URL_PRD }} | |
| INFERENCE_API_KEY: ${{ inputs.environment == 'dev' && secrets.INFERENCE_API_KEY_DEV || inputs.environment == 'stg' && secrets.INFERENCE_API_KEY_STG || secrets.INFERENCE_API_KEY_PRD }} | |
| MCP_BASIC_KEY: ${{ inputs.environment == 'dev' && secrets.MCP_BASIC_KEY_DEV || inputs.environment == 'stg' && secrets.MCP_BASIC_KEY_STG || secrets.MCP_BASIC_KEY_PRD }} | |
| MCP_PAPERSCORE_KEY: ${{ inputs.environment == 'dev' && secrets.MCP_PAPERSCORE_KEY_DEV || inputs.environment == 'stg' && secrets.MCP_PAPERSCORE_KEY_STG || secrets.MCP_PAPERSCORE_KEY_PRD }} | |
| XTRAMCP_OPENAI_BASE_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENAI_BASE_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENAI_BASE_URL_STG || secrets.XTRAMCP_OPENAI_BASE_URL_PRD }} | |
| XTRAMCP_OPENAI_API_KEY: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENAI_API_KEY_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENAI_API_KEY_STG || secrets.XTRAMCP_OPENAI_API_KEY_PRD }} | |
| XTRAMCP_OPENREVIEW_BASE_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_BASE_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_BASE_URL_STG || secrets.XTRAMCP_OPENREVIEW_BASE_URL_PRD }} | |
| XTRAMCP_OPENREVIEW_USERNAME: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_USERNAME_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_USERNAME_STG || secrets.XTRAMCP_OPENREVIEW_USERNAME_PRD }} | |
| XTRAMCP_OPENREVIEW_PASSWORD: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_OPENREVIEW_PASSWORD_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_OPENREVIEW_PASSWORD_STG || secrets.XTRAMCP_OPENREVIEW_PASSWORD_PRD }} | |
| XTRAMCP_CROSSREF_EMAIL_ADDRESS: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG || secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_PRD }} | |
| XTRAMCP_DOI_EMAIL_ADDRESS: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_DOI_EMAIL_ADDRESS_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_DOI_EMAIL_ADDRESS_STG || secrets.XTRAMCP_DOI_EMAIL_ADDRESS_PRD }} | |
| XTRAMCP_ACL_METADATA_DB_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_ACL_METADATA_DB_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_ACL_METADATA_DB_URL_STG || secrets.XTRAMCP_ACL_METADATA_DB_URL_PRD }} | |
| XTRAMCP_ARXIV_METADATA_DB_URL: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_ARXIV_METADATA_DB_URL_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_ARXIV_METADATA_DB_URL_STG || secrets.XTRAMCP_ARXIV_METADATA_DB_URL_PRD }} | |
| XTRAMCP_MONGO_URI: ${{ inputs.environment == 'dev' && secrets.XTRAMCP_MONGO_URI_DEV || inputs.environment == 'stg' && secrets.XTRAMCP_MONGO_URI_STG || secrets.XTRAMCP_MONGO_URI_PRD }} | |
| MONGO_URI: ${{ inputs.environment == 'dev' && secrets.MONGO_URI_DEV || inputs.environment == 'stg' && secrets.MONGO_URI_STG || secrets.MONGO_URI_PRD }} | |
| GHCR_DOCKER_CONFIG: ${{ inputs.environment == 'dev' && secrets.GHCR_DOCKER_CONFIG_DEV || inputs.environment == 'stg' && secrets.GHCR_DOCKER_CONFIG_STG || secrets.GHCR_DOCKER_CONFIG_PRD }} | |
| CLOUDFLARE_TUNNEL_TOKEN: ${{ inputs.environment == 'dev' && secrets.CLOUDFLARE_TUNNEL_TOKEN_DEV || inputs.environment == 'stg' && secrets.CLOUDFLARE_TUNNEL_TOKEN_STG || secrets.CLOUDFLARE_TUNNEL_TOKEN_PRD }} | |
| run: | | |
| OPENAI_BASE_URL_DEV: ${{ secrets.OPENAI_BASE_URL_DEV }} | |
| OPENAI_BASE_URL_STG: ${{ secrets.OPENAI_BASE_URL_STG }} | |
| OPENAI_BASE_URL_PRD: ${{ secrets.OPENAI_BASE_URL_PRD }} | |
| OPENAI_API_KEY_DEV: ${{ secrets.OPENAI_API_KEY_DEV }} | |
| OPENAI_API_KEY_STG: ${{ secrets.OPENAI_API_KEY_STG }} | |
| OPENAI_API_KEY_PRD: ${{ secrets.OPENAI_API_KEY_PRD }} | |
| INFERENCE_BASE_URL_DEV: ${{ secrets.INFERENCE_BASE_URL_DEV }} | |
| INFERENCE_BASE_URL_STG: ${{ secrets.INFERENCE_BASE_URL_STG }} | |
| INFERENCE_BASE_URL_PRD: ${{ secrets.INFERENCE_BASE_URL_PRD }} | |
| INFERENCE_API_KEY_DEV: ${{ secrets.INFERENCE_API_KEY_DEV }} | |
| INFERENCE_API_KEY_STG: ${{ secrets.INFERENCE_API_KEY_STG }} | |
| INFERENCE_API_KEY_PRD: ${{ secrets.INFERENCE_API_KEY_PRD }} | |
| MCP_BASIC_KEY_DEV: ${{ secrets.MCP_BASIC_KEY_DEV }} | |
| MCP_BASIC_KEY_STG: ${{ secrets.MCP_BASIC_KEY_STG }} | |
| MCP_BASIC_KEY_PRD: ${{ secrets.MCP_BASIC_KEY_PRD }} | |
| MCP_PAPERSCORE_KEY_DEV: ${{ secrets.MCP_PAPERSCORE_KEY_DEV }} | |
| MCP_PAPERSCORE_KEY_STG: ${{ secrets.MCP_PAPERSCORE_KEY_STG }} | |
| MCP_PAPERSCORE_KEY_PRD: ${{ secrets.MCP_PAPERSCORE_KEY_PRD }} | |
| XTRAMCP_OPENAI_BASE_URL_DEV: ${{ secrets.XTRAMCP_OPENAI_BASE_URL_DEV }} | |
| XTRAMCP_OPENAI_BASE_URL_STG: ${{ secrets.XTRAMCP_OPENAI_BASE_URL_STG }} | |
| XTRAMCP_OPENAI_BASE_URL_PRD: ${{ secrets.XTRAMCP_OPENAI_BASE_URL_PRD }} | |
| XTRAMCP_OPENAI_API_KEY_DEV: ${{ secrets.XTRAMCP_OPENAI_API_KEY_DEV }} | |
| XTRAMCP_OPENAI_API_KEY_STG: ${{ secrets.XTRAMCP_OPENAI_API_KEY_STG }} | |
| XTRAMCP_OPENAI_API_KEY_PRD: ${{ secrets.XTRAMCP_OPENAI_API_KEY_PRD }} | |
| XTRAMCP_OPENREVIEW_BASE_URL_DEV: ${{ secrets.XTRAMCP_OPENREVIEW_BASE_URL_DEV }} | |
| XTRAMCP_OPENREVIEW_BASE_URL_STG: ${{ secrets.XTRAMCP_OPENREVIEW_BASE_URL_STG }} | |
| XTRAMCP_OPENREVIEW_BASE_URL_PRD: ${{ secrets.XTRAMCP_OPENREVIEW_BASE_URL_PRD }} | |
| XTRAMCP_OPENREVIEW_USERNAME_DEV: ${{ secrets.XTRAMCP_OPENREVIEW_USERNAME_DEV }} | |
| XTRAMCP_OPENREVIEW_USERNAME_STG: ${{ secrets.XTRAMCP_OPENREVIEW_USERNAME_STG }} | |
| XTRAMCP_OPENREVIEW_USERNAME_PRD: ${{ secrets.XTRAMCP_OPENREVIEW_USERNAME_PRD }} | |
| XTRAMCP_OPENREVIEW_PASSWORD_DEV: ${{ secrets.XTRAMCP_OPENREVIEW_PASSWORD_DEV }} | |
| XTRAMCP_OPENREVIEW_PASSWORD_STG: ${{ secrets.XTRAMCP_OPENREVIEW_PASSWORD_STG }} | |
| XTRAMCP_OPENREVIEW_PASSWORD_PRD: ${{ secrets.XTRAMCP_OPENREVIEW_PASSWORD_PRD }} | |
| XTRAMCP_CROSSREF_EMAIL_ADDRESS_DEV: ${{ secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_DEV }} | |
| XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG: ${{ secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG }} | |
| XTRAMCP_CROSSREF_EMAIL_ADDRESS_PRD: ${{ secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_PRD }} | |
| XTRAMCP_DOI_EMAIL_ADDRESS_DEV: ${{ secrets.XTRAMCP_DOI_EMAIL_ADDRESS_DEV }} | |
| XTRAMCP_DOI_EMAIL_ADDRESS_STG: ${{ secrets.XTRAMCP_DOI_EMAIL_ADDRESS_STG }} | |
| XTRAMCP_DOI_EMAIL_ADDRESS_PRD: ${{ secrets.XTRAMCP_DOI_EMAIL_ADDRESS_PRD }} | |
| XTRAMCP_ACL_METADATA_DB_URL_DEV: ${{ secrets.XTRAMCP_ACL_METADATA_DB_URL_DEV }} | |
| XTRAMCP_ACL_METADATA_DB_URL_STG: ${{ secrets.XTRAMCP_ACL_METADATA_DB_URL_STG }} | |
| XTRAMCP_ACL_METADATA_DB_URL_PRD: ${{ secrets.XTRAMCP_ACL_METADATA_DB_URL_PRD }} | |
| XTRAMCP_ARXIV_METADATA_DB_URL_DEV: ${{ secrets.XTRAMCP_ARXIV_METADATA_DB_URL_DEV }} | |
| XTRAMCP_ARXIV_METADATA_DB_URL_STG: ${{ secrets.XTRAMCP_ARXIV_METADATA_DB_URL_STG }} | |
| XTRAMCP_ARXIV_METADATA_DB_URL_PRD: ${{ secrets.XTRAMCP_ARXIV_METADATA_DB_URL_PRD }} | |
| XTRAMCP_MONGO_URI_DEV: ${{ secrets.XTRAMCP_MONGO_URI_DEV }} | |
| XTRAMCP_MONGO_URI_STG: ${{ secrets.XTRAMCP_MONGO_URI_STG }} | |
| XTRAMCP_MONGO_URI_PRD: ${{ secrets.XTRAMCP_MONGO_URI_PRD }} | |
| MONGO_URI_DEV: ${{ secrets.MONGO_URI_DEV }} | |
| MONGO_URI_STG: ${{ secrets.MONGO_URI_STG }} | |
| MONGO_URI_PRD: ${{ secrets.MONGO_URI_PRD }} | |
| GHCR_DOCKER_CONFIG_DEV: ${{ secrets.GHCR_DOCKER_CONFIG_DEV }} | |
| GHCR_DOCKER_CONFIG_STG: ${{ secrets.GHCR_DOCKER_CONFIG_STG }} | |
| GHCR_DOCKER_CONFIG_PRD: ${{ secrets.GHCR_DOCKER_CONFIG_PRD }} | |
| CLOUDFLARE_TUNNEL_TOKEN_DEV: ${{ secrets.CLOUDFLARE_TUNNEL_TOKEN_DEV }} | |
| CLOUDFLARE_TUNNEL_TOKEN_STG: ${{ secrets.CLOUDFLARE_TUNNEL_TOKEN_STG }} | |
| CLOUDFLARE_TUNNEL_TOKEN_PRD: ${{ secrets.CLOUDFLARE_TUNNEL_TOKEN_PRD }} | |
| run: | | |
| set -euo pipefail | |
| case "${{ inputs.environment }}" in | |
| dev) | |
| export OPENAI_BASE_URL="$OPENAI_BASE_URL_DEV" | |
| export OPENAI_API_KEY="$OPENAI_API_KEY_DEV" | |
| export INFERENCE_BASE_URL="$INFERENCE_BASE_URL_DEV" | |
| export INFERENCE_API_KEY="$INFERENCE_API_KEY_DEV" | |
| export MCP_BASIC_KEY="$MCP_BASIC_KEY_DEV" | |
| export MCP_PAPERSCORE_KEY="$MCP_PAPERSCORE_KEY_DEV" | |
| export XTRAMCP_OPENAI_BASE_URL="$XTRAMCP_OPENAI_BASE_URL_DEV" | |
| export XTRAMCP_OPENAI_API_KEY="$XTRAMCP_OPENAI_API_KEY_DEV" | |
| export XTRAMCP_OPENREVIEW_BASE_URL="$XTRAMCP_OPENREVIEW_BASE_URL_DEV" | |
| export XTRAMCP_OPENREVIEW_USERNAME="$XTRAMCP_OPENREVIEW_USERNAME_DEV" | |
| export XTRAMCP_OPENREVIEW_PASSWORD="$XTRAMCP_OPENREVIEW_PASSWORD_DEV" | |
| export XTRAMCP_CROSSREF_EMAIL_ADDRESS="$XTRAMCP_CROSSREF_EMAIL_ADDRESS_DEV" | |
| export XTRAMCP_DOI_EMAIL_ADDRESS="$XTRAMCP_DOI_EMAIL_ADDRESS_DEV" | |
| export XTRAMCP_ACL_METADATA_DB_URL="$XTRAMCP_ACL_METADATA_DB_URL_DEV" | |
| export XTRAMCP_ARXIV_METADATA_DB_URL="$XTRAMCP_ARXIV_METADATA_DB_URL_DEV" | |
| export XTRAMCP_MONGO_URI="$XTRAMCP_MONGO_URI_DEV" | |
| export MONGO_URI="$MONGO_URI_DEV" | |
| export GHCR_DOCKER_CONFIG="$GHCR_DOCKER_CONFIG_DEV" | |
| export CLOUDFLARE_TUNNEL_TOKEN="$CLOUDFLARE_TUNNEL_TOKEN_DEV" | |
| ;; | |
| stg) | |
| export OPENAI_BASE_URL="$OPENAI_BASE_URL_STG" | |
| export OPENAI_API_KEY="$OPENAI_API_KEY_STG" | |
| export INFERENCE_BASE_URL="$INFERENCE_BASE_URL_STG" | |
| export INFERENCE_API_KEY="$INFERENCE_API_KEY_STG" | |
| export MCP_BASIC_KEY="$MCP_BASIC_KEY_STG" | |
| export MCP_PAPERSCORE_KEY="$MCP_PAPERSCORE_KEY_STG" | |
| export XTRAMCP_OPENAI_BASE_URL="$XTRAMCP_OPENAI_BASE_URL_STG" | |
| export XTRAMCP_OPENAI_API_KEY="$XTRAMCP_OPENAI_API_KEY_STG" | |
| export XTRAMCP_OPENREVIEW_BASE_URL="$XTRAMCP_OPENREVIEW_BASE_URL_STG" | |
| export XTRAMCP_OPENREVIEW_USERNAME="$XTRAMCP_OPENREVIEW_USERNAME_STG" | |
| export XTRAMCP_OPENREVIEW_PASSWORD="$XTRAMCP_OPENREVIEW_PASSWORD_STG" | |
| export XTRAMCP_CROSSREF_EMAIL_ADDRESS="$XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG" | |
| export XTRAMCP_DOI_EMAIL_ADDRESS="$XTRAMCP_DOI_EMAIL_ADDRESS_STG" | |
| export XTRAMCP_ACL_METADATA_DB_URL="$XTRAMCP_ACL_METADATA_DB_URL_STG" | |
| export XTRAMCP_ARXIV_METADATA_DB_URL="$XTRAMCP_ARXIV_METADATA_DB_URL_STG" | |
| export XTRAMCP_MONGO_URI="$XTRAMCP_MONGO_URI_STG" | |
| export MONGO_URI="$MONGO_URI_STG" | |
| export GHCR_DOCKER_CONFIG="$GHCR_DOCKER_CONFIG_STG" | |
| export CLOUDFLARE_TUNNEL_TOKEN="$CLOUDFLARE_TUNNEL_TOKEN_STG" | |
| ;; | |
| prd) | |
| export OPENAI_BASE_URL="$OPENAI_BASE_URL_PRD" | |
| export OPENAI_API_KEY="$OPENAI_API_KEY_PRD" | |
| export INFERENCE_BASE_URL="$INFERENCE_BASE_URL_PRD" | |
| export INFERENCE_API_KEY="$INFERENCE_API_KEY_PRD" | |
| export MCP_BASIC_KEY="$MCP_BASIC_KEY_PRD" | |
| export MCP_PAPERSCORE_KEY="$MCP_PAPERSCORE_KEY_PRD" | |
| export XTRAMCP_OPENAI_BASE_URL="$XTRAMCP_OPENAI_BASE_URL_PRD" | |
| export XTRAMCP_OPENAI_API_KEY="$XTRAMCP_OPENAI_API_KEY_PRD" | |
| export XTRAMCP_OPENREVIEW_BASE_URL="$XTRAMCP_OPENREVIEW_BASE_URL_PRD" | |
| export XTRAMCP_OPENREVIEW_USERNAME="$XTRAMCP_OPENREVIEW_USERNAME_PRD" | |
| export XTRAMCP_OPENREVIEW_PASSWORD="$XTRAMCP_OPENREVIEW_PASSWORD_PRD" | |
| export XTRAMCP_CROSSREF_EMAIL_ADDRESS="$XTRAMCP_CROSSREF_EMAIL_ADDRESS_PRD" | |
| export XTRAMCP_DOI_EMAIL_ADDRESS="$XTRAMCP_DOI_EMAIL_ADDRESS_PRD" | |
| export XTRAMCP_ACL_METADATA_DB_URL="$XTRAMCP_ACL_METADATA_DB_URL_PRD" | |
| export XTRAMCP_ARXIV_METADATA_DB_URL="$XTRAMCP_ARXIV_METADATA_DB_URL_PRD" | |
| export XTRAMCP_MONGO_URI="$XTRAMCP_MONGO_URI_PRD" | |
| export MONGO_URI="$MONGO_URI_PRD" | |
| export GHCR_DOCKER_CONFIG="$GHCR_DOCKER_CONFIG_PRD" | |
| export CLOUDFLARE_TUNNEL_TOKEN="$CLOUDFLARE_TUNNEL_TOKEN_PRD" | |
| ;; | |
| *) | |
| echo "ERROR: Invalid environment '${{ inputs.environment }}'. Expected 'dev', 'stg', or 'prd'." >&2 | |
| exit 1 | |
| ;; | |
| esac |
| zip -r dist.zip dist/* | ||
|
|
||
| - name: Upload to Chrome Web Store (upload only) | ||
| uses: mobilefirstllc/cws-publish@latest |
There was a problem hiding this comment.
mobilefirstllc/cws-publish@latest is a floating ref, which can change behavior unexpectedly and is a supply-chain risk. Pin to a specific version tag or (preferably) a commit SHA so builds are reproducible and updates are intentional.
| uses: mobilefirstllc/cws-publish@latest | |
| uses: mobilefirstllc/cws-publish@v1.0.6 |
| ref: ${{ inputs.ref }} | ||
| - name: Clone deploy repo | ||
| run: | | ||
| git clone https://${{ secrets.GH_PAT }}@github.com/paperdebugger/deploy.git ../deploy |
There was a problem hiding this comment.
Cloning with https://${{ secrets.GH_PAT }}@github.com/... can break if the token contains URL-significant characters and also embeds the credential in the command string. Prefer actions/checkout with repository: + path: + token:, or use the https://x-access-token:<token>@github.com/... form to avoid parsing issues.
| git clone https://${{ secrets.GH_PAT }}@github.com/paperdebugger/deploy.git ../deploy | |
| git clone https://x-access-token:${{ secrets.GH_PAT }}@github.com/paperdebugger/deploy.git ../deploy |
| zip_file: 'dist.zip' | ||
| build-and-publish: | ||
| uses: ./.github/workflows/_build-ext.yml | ||
| secrets: inherit |
There was a problem hiding this comment.
Using secrets: inherit passes all repository/environment secrets into the called workflow, which is broader than needed for the extension build/publish and increases blast radius if the called workflow is modified later. After declaring required secrets in _build-ext.yml, pass only the needed secrets explicitly from this caller.
| secrets: inherit | |
| secrets: | |
| CHROME_WEBSTORE_CLIENT_ID: ${{ secrets.CHROME_WEBSTORE_CLIENT_ID }} | |
| CHROME_WEBSTORE_CLIENT_SECRET: ${{ secrets.CHROME_WEBSTORE_CLIENT_SECRET }} | |
| CHROME_WEBSTORE_REFRESH_TOKEN: ${{ secrets.CHROME_WEBSTORE_REFRESH_TOKEN }} |
Summary
_build-backend.yml,_build-ext.yml) to eliminate duplicated build/deploy logic across dev/stg/prdpush: tags: v*trigger from stg/prd backend workflows to prevent double builds (bump-version already dispatches viarepository_dispatch). Also fixes a bug where a staging tag push could accidentally trigger a production buildbuild-ext-dev.yml8 files changed, net -177 lines.
Test plan
build-backend-stgandbuild-ext-stgcorrectlybuild-backend-prdandbuild-ext-prdcorrectlydevelopmentbranch triggersbuild-backend-devcorrectly🤖 Generated with Claude Code