Skip to content
Merged
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
12 changes: 7 additions & 5 deletions actions/setup/js/extra_empty_commit.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
* GITHUB_TOKEN do not trigger other workflow runs.
*
* The token comes from `github-token-for-extra-empty-commit` in safe-outputs config
* (passed as GH_AW_EXTRA_EMPTY_COMMIT_TOKEN env var). Supported values:
* - `app` - Use GitHub App token from safe-outputs-app-token step
* - `default` - Use the magic secret GH_AW_CI_TRIGGER_TOKEN
* - `${{ secrets.CUSTOM_TOKEN }}` - Use a custom PAT or secret
* and is passed in as the GH_AW_CI_TRIGGER_TOKEN environment variable.
* By the time this script runs, GH_AW_CI_TRIGGER_TOKEN must contain an actual
* GitHub authentication token (for example, a GitHub App token or a PAT).
* Any selection or defaulting behavior (such as resolving `app`, `default`,
* or a specific secret reference) is handled in the workflow compiler/config
* layer before this script is invoked.
*/

/**
Expand All @@ -28,7 +30,7 @@
* @returns {Promise<{success: boolean, skipped?: boolean, error?: string}>}
*/
async function pushExtraEmptyCommit({ branchName, repoOwner, repoName, commitMessage }) {
const token = process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN;
const token = process.env.GH_AW_CI_TRIGGER_TOKEN;

if (!token || !token.trim()) {
core.info("No extra empty commit token configured - skipping");
Expand Down
18 changes: 9 additions & 9 deletions actions/setup/js/extra_empty_commit.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("extra_empty_commit.cjs", () => {
let originalEnv;

beforeEach(() => {
originalEnv = process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN;
originalEnv = process.env.GH_AW_CI_TRIGGER_TOKEN;

mockCore = {
info: vi.fn(),
Expand All @@ -30,9 +30,9 @@ describe("extra_empty_commit.cjs", () => {

afterEach(() => {
if (originalEnv !== undefined) {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = originalEnv;
process.env.GH_AW_CI_TRIGGER_TOKEN = originalEnv;
} else {
delete process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN;
delete process.env.GH_AW_CI_TRIGGER_TOKEN;
}
delete global.core;
delete global.exec;
Expand All @@ -59,7 +59,7 @@ describe("extra_empty_commit.cjs", () => {

describe("when no extra empty commit token is set", () => {
it("should skip and return success with skipped=true", async () => {
delete process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN;
delete process.env.GH_AW_CI_TRIGGER_TOKEN;
({ pushExtraEmptyCommit } = require("./extra_empty_commit.cjs"));

const result = await pushExtraEmptyCommit({
Expand All @@ -74,7 +74,7 @@ describe("extra_empty_commit.cjs", () => {
});

it("should skip when token is empty string", async () => {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = "";
process.env.GH_AW_CI_TRIGGER_TOKEN = "";
({ pushExtraEmptyCommit } = require("./extra_empty_commit.cjs"));

const result = await pushExtraEmptyCommit({
Expand All @@ -87,7 +87,7 @@ describe("extra_empty_commit.cjs", () => {
});

it("should skip when token is whitespace only", async () => {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = " ";
process.env.GH_AW_CI_TRIGGER_TOKEN = " ";
({ pushExtraEmptyCommit } = require("./extra_empty_commit.cjs"));

const result = await pushExtraEmptyCommit({
Expand All @@ -106,7 +106,7 @@ describe("extra_empty_commit.cjs", () => {

describe("when token is set and no cycle issues", () => {
beforeEach(() => {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = "ghp_test_token_123";
process.env.GH_AW_CI_TRIGGER_TOKEN = "ghp_test_token_123";
// Simulate git log showing 5 commits, all with file changes (non-empty)
const logOutput = ["COMMIT:aaa111", "file1.txt", "", "COMMIT:bbb222", "file2.txt", "file3.txt", "", "COMMIT:ccc333", "file4.txt", "", "COMMIT:ddd444", "file5.txt", "", "COMMIT:eee555", "file6.txt", ""].join("\n");
mockGitLogOutput(logOutput);
Expand Down Expand Up @@ -187,7 +187,7 @@ describe("extra_empty_commit.cjs", () => {

describe("cycle prevention", () => {
beforeEach(() => {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = "ghp_test_token_123";
process.env.GH_AW_CI_TRIGGER_TOKEN = "ghp_test_token_123";
({ pushExtraEmptyCommit } = require("./extra_empty_commit.cjs"));
});

Expand Down Expand Up @@ -327,7 +327,7 @@ describe("extra_empty_commit.cjs", () => {

describe("error handling", () => {
beforeEach(() => {
process.env.GH_AW_EXTRA_EMPTY_COMMIT_TOKEN = "ghp_test_token_123";
process.env.GH_AW_CI_TRIGGER_TOKEN = "ghp_test_token_123";
// No empty commits in log
mockGitLogOutput("COMMIT:abc123\nfile.txt\n");
({ pushExtraEmptyCommit } = require("./extra_empty_commit.cjs"));
Expand Down
4 changes: 2 additions & 2 deletions pkg/parser/schemas/main_workflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5169,7 +5169,7 @@
},
"github-token-for-extra-empty-commit": {
"type": "string",
"description": "Token used to push an empty commit after PR creation to trigger CI events. Works around the GITHUB_TOKEN limitation where pushes don't trigger workflow runs. Use a secret expression (e.g. '${{ secrets.CI_TOKEN }}'), 'app' for GitHub App auth, or 'default' to use the magic secret GH_AW_CI_TRIGGER_TOKEN."
"description": "Token used to push an empty commit after PR creation to trigger CI events. Works around the GITHUB_TOKEN limitation where pushes don't trigger workflow runs. Defaults to the magic secret GH_AW_CI_TRIGGER_TOKEN if set in the repository. Use a secret expression (e.g. '${{ secrets.CI_TOKEN }}') for a custom token, or 'app' for GitHub App auth."
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -6150,7 +6150,7 @@
},
"github-token-for-extra-empty-commit": {
"type": "string",
"description": "Token used to push an empty commit after pushing changes to trigger CI events. Works around the GITHUB_TOKEN limitation where pushes don't trigger workflow runs. Use a secret expression (e.g. '${{ secrets.CI_TOKEN }}'), 'app' for GitHub App auth, or 'default' to use the magic secret GH_AW_CI_TRIGGER_TOKEN."
"description": "Token used to push an empty commit after pushing changes to trigger CI events. Works around the GITHUB_TOKEN limitation where pushes don't trigger workflow runs. Defaults to the magic secret GH_AW_CI_TRIGGER_TOKEN if set in the repository. Use a secret expression (e.g. '${{ secrets.CI_TOKEN }}') for a custom token, or 'app' for GitHub App auth."
}
},
"additionalProperties": false
Expand Down
21 changes: 11 additions & 10 deletions pkg/workflow/compiler_safe_outputs_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,22 +409,23 @@ func (c *Compiler) buildJobLevelSafeOutputEnvVars(data *WorkflowData, workflowID
// This token is used to push an empty commit after code changes to trigger CI events,
// working around the GITHUB_TOKEN limitation where events don't trigger other workflows.
if data.SafeOutputs != nil {
var extraEmptyCommitToken string
var ciTriggerToken string
if data.SafeOutputs.CreatePullRequests != nil && data.SafeOutputs.CreatePullRequests.GithubTokenForExtraEmptyCommit != "" {
extraEmptyCommitToken = data.SafeOutputs.CreatePullRequests.GithubTokenForExtraEmptyCommit
ciTriggerToken = data.SafeOutputs.CreatePullRequests.GithubTokenForExtraEmptyCommit
} else if data.SafeOutputs.PushToPullRequestBranch != nil && data.SafeOutputs.PushToPullRequestBranch.GithubTokenForExtraEmptyCommit != "" {
extraEmptyCommitToken = data.SafeOutputs.PushToPullRequestBranch.GithubTokenForExtraEmptyCommit
ciTriggerToken = data.SafeOutputs.PushToPullRequestBranch.GithubTokenForExtraEmptyCommit
}

if extraEmptyCommitToken == "app" {
envVars["GH_AW_EXTRA_EMPTY_COMMIT_TOKEN"] = "${{ steps.safe-outputs-app-token.outputs.token || '' }}"
switch ciTriggerToken {
case "app":
envVars["GH_AW_CI_TRIGGER_TOKEN"] = "${{ steps.safe-outputs-app-token.outputs.token || '' }}"
consolidatedSafeOutputsJobLog.Print("Extra empty commit using GitHub App token")
} else if extraEmptyCommitToken == "default" {
// Use the magic GH_AW_CI_TRIGGER_TOKEN secret as fallback
envVars["GH_AW_EXTRA_EMPTY_COMMIT_TOKEN"] = getEffectiveCITriggerGitHubToken("")
case "default", "":
// Use the magic GH_AW_CI_TRIGGER_TOKEN secret (default behavior when not explicitly configured)
envVars["GH_AW_CI_TRIGGER_TOKEN"] = getEffectiveCITriggerGitHubToken("")
consolidatedSafeOutputsJobLog.Print("Extra empty commit using GH_AW_CI_TRIGGER_TOKEN")
} else if extraEmptyCommitToken != "" {
envVars["GH_AW_EXTRA_EMPTY_COMMIT_TOKEN"] = extraEmptyCommitToken
default:
envVars["GH_AW_CI_TRIGGER_TOKEN"] = ciTriggerToken
consolidatedSafeOutputsJobLog.Print("Extra empty commit using explicit token")
}
}
Expand Down
28 changes: 14 additions & 14 deletions pkg/workflow/create_pull_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,20 +165,20 @@ func (c *Compiler) buildCreateOutputPullRequestJob(data *WorkflowData, mainJobNa
createPRLog.Print("Footer disabled - XML markers will be included but visible footer content will be omitted")
}

// Add extra empty commit token if configured (for pushing an empty commit to trigger CI)
extraEmptyCommitToken := data.SafeOutputs.CreatePullRequests.GithubTokenForExtraEmptyCommit
if extraEmptyCommitToken != "" {
if extraEmptyCommitToken == "app" {
customEnvVars = append(customEnvVars, " GH_AW_EXTRA_EMPTY_COMMIT_TOKEN: ${{ steps.safe-outputs-app-token.outputs.token || '' }}\n")
createPRLog.Print("Extra empty commit using GitHub App token")
} else if extraEmptyCommitToken == "default" {
// Use the magic GH_AW_CI_TRIGGER_TOKEN secret as fallback
customEnvVars = append(customEnvVars, fmt.Sprintf(" GH_AW_EXTRA_EMPTY_COMMIT_TOKEN: %s\n", getEffectiveCITriggerGitHubToken("")))
createPRLog.Print("Extra empty commit using GH_AW_CI_TRIGGER_TOKEN")
} else {
customEnvVars = append(customEnvVars, fmt.Sprintf(" GH_AW_EXTRA_EMPTY_COMMIT_TOKEN: %s\n", extraEmptyCommitToken))
createPRLog.Printf("Extra empty commit using explicit token")
}
// Add extra empty commit token (for pushing an empty commit to trigger CI)
// Defaults to GH_AW_CI_TRIGGER_TOKEN when not explicitly configured
ciTriggerToken := data.SafeOutputs.CreatePullRequests.GithubTokenForExtraEmptyCommit
switch ciTriggerToken {
case "app":
customEnvVars = append(customEnvVars, " GH_AW_CI_TRIGGER_TOKEN: ${{ steps.safe-outputs-app-token.outputs.token || '' }}\n")
createPRLog.Print("Extra empty commit using GitHub App token")
case "default", "":
// Use the magic GH_AW_CI_TRIGGER_TOKEN secret (default behavior when not explicitly configured)
customEnvVars = append(customEnvVars, fmt.Sprintf(" GH_AW_CI_TRIGGER_TOKEN: %s\n", getEffectiveCITriggerGitHubToken("")))
createPRLog.Print("Extra empty commit using GH_AW_CI_TRIGGER_TOKEN")
default:
customEnvVars = append(customEnvVars, fmt.Sprintf(" GH_AW_CI_TRIGGER_TOKEN: %s\n", ciTriggerToken))
createPRLog.Printf("Extra empty commit using explicit token")
}

// Add standard environment variables (metadata + staged/target repo)
Expand Down
Loading
Loading