Skip to content
Open
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: 27 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
id-token: write
outputs:
version: ${{ steps.set_version.outputs.version }}

Expand All @@ -31,7 +34,17 @@ jobs:
with:
fetch-depth: 0
fetch-tags: true
ref: ${{ github.event.inputs.commit_sha || github.ref_name }}
ref: ${{ github.event.inputs['commit_sha'] || github.ref_name }}

- name: Fetch secrets from Infisical
uses: WriterInternal/devops-github-actions/infisical-secrets@cf0625c0cb6646c057b9bc81c49c8554b2313e27 # v2.3.0
with:
org-identity-id: ${{ secrets.INFISICAL_ORG_IDENTITY_UUID }}
org-project-slug: ${{ secrets.INFISICAL_ORG_PROJECT_SLUG }}
repo-identity-id: ${{ secrets.INFISICAL_REPO_IDENTITY_UUID }}
repo-project-slug: ${{ secrets.INFISICAL_REPO_PROJECT_SLUG }}
env-slug: prod
required-keys: LAUNCHDARKLY_ACCESS_TOKEN PYPI_TOKEN
Comment on lines +39 to +47

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Fetch publish secrets closer to their consumers.

This step exports both LAUNCHDARKLY_ACCESS_TOKEN and PYPI_TOKEN before dependency install/build commands run, broadening token exposure beyond the upload/publish steps. Prefer fetching each token immediately before the step that needs it, or use step-scoped outputs/env if the composite action supports that.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml around lines 39 - 47, Move the Infisical
secret fetches in publish workflow closer to where they are used so the tokens
are not exposed for the whole job. In the publish job, refactor the
secret-loading step that uses infisical-secrets to fetch
LAUNCHDARKLY_ACCESS_TOKEN only before the build-related step that needs it and
PYPI_TOKEN only immediately before the publish/upload step, or scope them via
step outputs/env if supported. Keep the existing publish job flow intact while
limiting token lifetime around the relevant consumer steps.


- name: Set up Python
uses: actions/setup-python@v5
Expand Down Expand Up @@ -81,10 +94,12 @@ jobs:

- name: Determine final version
id: set_version
env:
INPUT_VERSION: ${{ github.event.inputs['version'] }}
run: |
# Determine version based on workflow inputs or tags
if [ -n "${{ github.event.inputs.version }}" ]; then
VERSION="${{ github.event.inputs.version }}"
if [ -n "$INPUT_VERSION" ]; then
VERSION="$INPUT_VERSION"
elif [ "${GITHUB_REF_NAME}" = "dev" ]; then
VERSION="${{ steps.bump_version.outputs.version }}"
elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
Expand Down Expand Up @@ -116,7 +131,7 @@ jobs:
- name: Upload sourcemaps to LaunchDarkly
shell: bash
env:
LAUNCHDARKLY_ACCESS_TOKEN: ${{ secrets.LAUNCHDARKLY_ACCESS_TOKEN }}
LAUNCHDARKLY_ACCESS_TOKEN: ${{ env.LAUNCHDARKLY_ACCESS_TOKEN }}
RELEASE_VERSION: ${{ steps.set_version.outputs.version }}
BASE_PATH: /static
PROJECT: writer-framework
Expand All @@ -130,7 +145,7 @@ jobs:
WRITER_FRAMEWORK_VERSION=${{ steps.set_version.outputs.version }} poetry run alfred install.ci
WRITER_FRAMEWORK_VERSION=${{ steps.set_version.outputs.version }} poetry run alfred publish.pypi
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
PYPI_TOKEN: ${{ env.PYPI_TOKEN }}

- name: Create and push tag for RC (only dev)
if: github.ref_name == 'dev'
Expand All @@ -148,9 +163,15 @@ jobs:
trigger-agent-manager:
needs: [build]
if: github.ref_name == 'dev'
permissions:
contents: read
id-token: write
uses: ./.github/workflows/trigger-workflow.yml
with:
event_type: framework_updated
extra_payload: '{"tag": "writer-framework-${{ needs.build.outputs.version }}", "version": "${{ needs.build.outputs.version }}"}'
secrets:
AGENT_MANAGER_PAT: ${{ secrets.AGENT_MANAGER_PAT }}
INFISICAL_ORG_IDENTITY_UUID: ${{ secrets.INFISICAL_ORG_IDENTITY_UUID }}
INFISICAL_ORG_PROJECT_SLUG: ${{ secrets.INFISICAL_ORG_PROJECT_SLUG }}
INFISICAL_REPO_IDENTITY_UUID: ${{ secrets.INFISICAL_REPO_IDENTITY_UUID }}
INFISICAL_REPO_PROJECT_SLUG: ${{ secrets.INFISICAL_REPO_PROJECT_SLUG }}
31 changes: 26 additions & 5 deletions .github/workflows/trigger-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ on:
type: string
default: "{}"
secrets:
AGENT_MANAGER_PAT:
description: 'Personal Access Token for triggering agent manager repo'
INFISICAL_ORG_IDENTITY_UUID:
required: true
INFISICAL_ORG_PROJECT_SLUG:
required: true
INFISICAL_REPO_IDENTITY_UUID:
required: true
INFISICAL_REPO_PROJECT_SLUG:
required: true

permissions:
Expand All @@ -23,15 +28,31 @@ permissions:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write

steps:
- name: Fetch secrets from Infisical
uses: WriterInternal/devops-github-actions/infisical-secrets@cf0625c0cb6646c057b9bc81c49c8554b2313e27 # v2.3.0
with:
org-identity-id: ${{ secrets.INFISICAL_ORG_IDENTITY_UUID }}
org-project-slug: ${{ secrets.INFISICAL_ORG_PROJECT_SLUG }}
repo-identity-id: ${{ secrets.INFISICAL_REPO_IDENTITY_UUID }}
repo-project-slug: ${{ secrets.INFISICAL_REPO_PROJECT_SLUG }}
env-slug: prod
required-keys: AGENT_MANAGER_PAT

- name: Trigger agent manager
env:
EVENT_TYPE: ${{ inputs.event_type }}
EXTRA_PAYLOAD: ${{ inputs.extra_payload }}
run: |
repo_owner="WriterInternal"
repo_name="be.agent-manager"
event_type="${{ inputs.event_type }}"
event_type="$EVENT_TYPE"
commit_sha="${{ github.sha }}"
extra_payload='${{ inputs.extra_payload }}'
extra_payload="$EXTRA_PAYLOAD"

echo "Triggering agent manager with event_type=$event_type"
echo "Extra payload (raw): $extra_payload"
Expand All @@ -48,7 +69,7 @@ jobs:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.AGENT_MANAGER_PAT }}" \
-H "Authorization: Bearer $AGENT_MANAGER_PAT" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$repo_owner/$repo_name/dispatches \
-d "{\"event_type\": \"$event_type\", \"client_payload\": $merged_payload}"
Comment on lines 69 to 75

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail the job when the dispatch API rejects the migrated PAT.

If Infisical returns a missing/mis-scoped AGENT_MANAGER_PAT, GitHub can respond with 401/403 while curl still exits successfully. Add an explicit token guard and HTTP failure handling so the release does not appear successful when the agent-manager dispatch was skipped.

Suggested hardening
+        : "${AGENT_MANAGER_PAT:?AGENT_MANAGER_PAT was not populated by Infisical}"
+
-        curl -L \
+        curl --fail --show-error --silent -L \
           -X POST \
           -H "Accept: application/vnd.github+json" \
           -H "Authorization: Bearer $AGENT_MANAGER_PAT" \
#!/bin/bash
# Verify the dispatch curl invocation has explicit HTTP failure handling.
fd -i 'trigger-workflow.yml' .github/workflows --exec awk 'NR>=69 && NR<=75 {print NR ":" $0}' {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/trigger-workflow.yml around lines 69 - 75, The dispatch
step currently can succeed even when AGENT_MANAGER_PAT is missing or rejected,
so the workflow may look successful while the agent-manager trigger never
happened. In the trigger-workflow.yml dispatch block, add a guard before the
curl call to verify AGENT_MANAGER_PAT is present, and change the curl invocation
to fail the job on non-2xx HTTP responses by checking the returned status from
the dispatch request. Keep the fix localized to the dispatch logic that uses
repo_owner, repo_name, event_type, merged_payload, and AGENT_MANAGER_PAT.

Loading