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.
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 Type | Trigger Condition | Common Use Case |
|---|---|---|
published | A release is published (or draft transitioned to published) | Generating production artifacts, container publishing |
created | A release draft or release is initially saved | Initial tag validation, pre-flight checks |
prereleased | A release marked as a pre-release is published | Publishing alpha/beta packages to test feeds |
released | A published release or pre-release is created | General release notifications |
edited | Release notes or title are modified | Synchronizing documentation or changelogs |
deleted | A release is deleted | Cleanup of remote package registries |
unpublished | A release is reverted to unpublished state | Revoking 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_requestisnull(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:
- 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 usingactions/upload-artifact. - When the
pull_requestworkflow completes, the downstreamworkflow_runworkflow triggers. - The downstream workflow executes in the context of the default branch (
main) with full repository secrets and write permissions. - 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
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 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?
An automated publishing workflow is configured with on: release: types: [published]. When will this workflow execute?