2.3 Release, Issue, and Dynamic Lifecycle Events

Key Takeaways

  • The release event fires on release lifecycle changes, distinguishing between draft creation (created), pre-releases (prereleased), and official distribution (published).
  • The issue_comment event triggers on comments added to both standard GitHub issues and pull requests, requiring conditional checks on github.event.issue.pull_request to differentiate between them.
  • The workflow_run event enables workflow chaining, triggering a downstream workflow when an upstream workflow begins or completes on default or targeted branches.
  • Downstream workflows triggered by workflow_run execute in the context of the default branch with write permissions and secret access, providing a secure method to process untrusted fork PR build artifacts.
  • Multiple event triggers can be combined within a single on: block, allowing unified workflows to handle code pushes, PR validation, schedules, and manual executions.
Last updated: August 2026

Release, Issue, and Dynamic Lifecycle Events

Beyond code check-ins and cron schedules, GitHub Actions integrates directly with GitHub's rich collaboration platform. Workflows can respond to releases, issue updates, pull request reviews, and even the completion of other independent workflows.

Mastering these advanced triggers enables developers to implement automated ChatOps, artifact publication pipelines, dynamic security triage, and multi-stage workflow orchestration.


1. Release Lifecycle Events (release)

The release event triggers whenever a GitHub Release is created, modified, or deleted. It is the industry standard trigger for compiling distribution binaries, building Docker release containers, and publishing packages to registries like npm, PyPI, or GitHub Packages.

Activity Types

If types is omitted, the release event defaults to triggering on published, created, and edited.

Activity TypeTrigger ConditionCommon Use Case
publishedA release is published (or draft transitioned to published)Generating production artifacts, container publishing
createdA release draft or release is initially savedInitial tag validation, pre-flight checks
prereleasedA release marked as a pre-release is publishedPublishing alpha/beta packages to test feeds
releasedA published release or pre-release is createdGeneral release notifications
editedRelease notes or title are modifiedSynchronizing documentation or changelogs
deletedA release is deletedCleanup of remote package registries
unpublishedA release is reverted to unpublished stateRevoking deployment manifests
name: Publish Production Artifacts
on:
  release:
    types: [published]

jobs:
  publish-package:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'
      - run: npm ci
      - run: npm publish --provenance --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

2. Project Collaboration Triggers: issues and issue_comment

GitHub Actions allows teams to automate repository hygiene and build interactive ChatOps workflows directly within issue and pull request comment threads.

The issues Event

Triggers on issue management actions. Supported types include: opened, edited, deleted, transferred, pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, milestoned, demilestoned.

The issue_comment Dual-Nature Mechanism

The issue_comment event fires whenever a comment is created, edited, or deleted on an issue. Crucially, in GitHub's internal data model, a Pull Request is also an Issue. Therefore, comments posted on pull requests also trigger issue_comment.

To build ChatOps commands (e.g., typing /deploy staging or /retest in a PR comment), workflows must verify that the comment originated from a pull request rather than a traditional issue:

name: PR ChatOps Command Handler
on:
  issue_comment:
    types: [created]

jobs:
  chatops-deploy:
    # Verify that comment is on a PR AND starts with /deploy
    if: ${{ github.event.issue.pull_request != null && startsWith(github.event.comment.body, '/deploy') }}
    runs-on: ubuntu-latest
    steps:
      - name: React to Comment
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.reactions.createForIssueComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              comment_id: context.payload.comment.id,
              content: 'rocket'
            });
      
      - name: Trigger Deployment
        run: |
          echo "Triggering deployment for PR #${{ github.event.issue.number }}"
          echo "Requested by @${{ github.event.comment.user.login }}"

[!NOTE] Notice the check: github.event.issue.pull_request != null. For regular issues, github.event.issue.pull_request is null (undefined). For pull requests, it contains an object with PR URLs (html_url, diff_url, patch_url).

3. Workflow Chaining with workflow_run

In complex enterprise pipelines, one workflow often needs to trigger another workflow upon completion. The workflow_run event allows a workflow to execute whenever a designated upstream workflow is completed or requested.

Core Syntax and Execution Context

name: Post-CI SonarQube & Security Ingestion
on:
  workflow_run:
    workflows: ["Continuous Integration Build"]
    types:
      - completed
    branches:
      - main
      - 'releases/**'

jobs:
  on-success:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - name: Download Build Artifacts from Triggering Workflow
        uses: actions/github-script@v7
        with:
          script: |
            const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
              owner: context.repo.owner,
              repo: context.repo.repo,
              run_id: context.payload.workflow_run.id
            });
            const matchArtifact = artifacts.data.artifacts.find(a => a.name === 'coverage-report');
            const download = await github.rest.actions.downloadArtifact({
              owner: context.repo.owner,
              repo: context.repo.repo,
              artifact_id: matchArtifact.id,
              archive_format: 'zip'
            });
            const fs = require('fs');
            fs.writeFileSync('coverage.zip', Buffer.from(download.data));
      
      - name: Ingest to SonarQube with Privileged Secrets
        run: ./scripts/sonar-upload.sh
        env:
          SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

The Security Advantage of workflow_run

The workflow_run event is the primary architectural solution for securely handling fork pull request artifacts:

  1. The initial workflow (pull_request) runs untrusted fork code in an unprivileged sandbox (read-only token, zero secrets), executes tests, and uploads coverage/test artifacts using actions/upload-artifact.
  2. When the pull_request workflow completes, the downstream workflow_run workflow triggers.
  3. The downstream workflow executes in the context of the default branch (main) with full repository secrets and write permissions.
  4. It securely downloads the artifacts generated by the untrusted PR and uploads them to internal metrics/scanning servers without exposing credentials to untrusted code.

4. Combining Multiple Events in Single Workflows

GitHub Actions supports combining diverse event triggers into a single unified workflow file under the on: key:

name: Comprehensive CI/CD Pipeline
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 4 * * *'
  workflow_dispatch:
    inputs:
      force_deploy:
        description: 'Force deployment bypass'
        type: boolean
        default: false

Determining Trigger Source at Runtime

When multiple events are combined, individual jobs or steps can adapt their behavior using the ${{ github.event_name }} context:

steps:
  - name: Run Full Integration Suite on Nightly Schedule Only
    if: ${{ github.event_name == 'schedule' || inputs.force_deploy == true }}
    run: npm run test:e2e:extended
Test Your Knowledge

A developer writes a workflow triggered on issue_comment with types: [created] to implement a ChatOps bot that triggers deployments when a user writes /deploy in a pull request conversation. How can the workflow verify that the comment was posted on a pull request rather than a regular issue?

A
B
C
D
Test Your Knowledge

A security team wants to run SonarQube code analysis and post results to pull requests opened from external forks. They need to prevent fork authors from accessing the SonarQube API secret while still analyzing PR test coverage data. Which design pattern fulfills these requirements securely?

A
B
C
D
Test Your Knowledge

An automated publishing workflow is configured with on: release: types: [published]. When will this workflow execute?

A
B
C
D