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
14 changes: 13 additions & 1 deletion .github/workflows/php-common-bump.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ on:
required: false
type: boolean
default: false
skip_ci:
description: "Append [skip actions] to the bump commit so it does NOT trigger workflows."
required: false
type: boolean
default: true
secrets:
write_pat:
required: true
Expand Down Expand Up @@ -71,6 +76,9 @@ jobs:
command: composer update revolutionparts/common --prefer-dist --no-interaction --no-progress --optimize-autoloader --apcu-autoloader
- name: Commit Common Bump
id: commit
env:
SKIP_CI: ${{ inputs.skip_ci }}
COMMIT_MESSAGE: ${{ inputs.commit_message }}
run: |
git config user.name github-actions
git config user.email github-actions@github.com
Expand All @@ -82,7 +90,11 @@ jobs:
exit 0
fi

git commit -am "${{ inputs.commit_message }} [skip actions]"
SUFFIX=""
if [ "$SKIP_CI" = "true" ]; then
SUFFIX=" [skip actions]"
fi
git commit -am "${COMMIT_MESSAGE}${SUFFIX}"

# Push with retry logic to handle race conditions where main has moved
MAX_ATTEMPTS=5
Expand Down
194 changes: 194 additions & 0 deletions docs/superpowers/plans/2026-06-10-common-bump-build-on-nightly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Nightly Common Bump Build-on-Tag Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Make a nightly `revolutionparts/common` bump produce a new build/tag (and, for repos with an integration pipeline, an integration deploy) instead of being suppressed by `[skip actions]`.

**Architecture:** Add an optional `skip_ci` input (default `true`, fully backward-compatible) to the shared `php-common-bump.yaml`; the bump commit appends `[skip actions]` only when `skip_ci` is true. The 11 repos that have a nightly common-update workflow opt in by passing `skip_ci: false`. The merge-path `upgrade-common.yaml` is left untouched (keeps skipping → no merge double-builds).

**Tech Stack:** GitHub Actions reusable workflows (`workflow_call`), `mathieudutour/github-tag-action`, `REPO_WRITE_PAT` (PAT pushes trigger workflows).

**Spec:** `docs/superpowers/specs/2026-06-10-common-bump-build-on-nightly-design.md`
**Ticket:** DEVEX-1628.

---

## How "tests" work here

There is no unit harness for workflows, and a common bump only commits when common **actually
changed** (a `git diff-index` guard), so a build can't be forced on demand without mutating
`main`. Verification is therefore:
1. **Static lint** — `actionlint` on every changed file.
2. **Logic review** — confirm the conditional `[skip actions]` suffix is correct.
3. **Live observation** — after merge + opt-in, `workflow_dispatch` the pilot's nightly workflow
and read the run: if common changed, confirm the bump commit has **no** `[skip actions]` and a
`Build` run was triggered; if common was already current, confirm the run no-ops cleanly
(expected) and confirm correctness on the next real common change.

Reusable workflows are referenced by ref. The `skip_ci` input must exist on
`encodium/.github` **`main`** before any caller passes it (an unknown input fails the call), so
**Task 1 (the shared change) must merge before the opt-in PRs (Tasks 3+)**.

---

## File Structure

**`encodium/.github` (shared — merges first):**
- Modify: `.github/workflows/php-common-bump.yaml` — add `skip_ci` input; conditional `[skip actions]`.

**Per service repo (one PR each) — add `skip_ci: false` to the nightly common-update workflow's `with:` block:**
- `Nightly Common Update.yaml` (8): rp_api, internal_api, catalog_api, license_api, returns-api, accounts-api, webstore, listings-url-service
- `nightly-common-update.yaml` (3): listings, marketplaces, payments

---

## Task 1: Add `skip_ci` input to `php-common-bump.yaml`

**Files:** Modify `.github/workflows/php-common-bump.yaml` (worktree `~/dev/claude/github-DEVEX-1628`, branch `DEVEX-1628-common-bump-build-on-nightly`).

- [ ] **Step 1: Add the input.** Under `on.workflow_call.inputs`, after `continue_on_error`, add:

```yaml
skip_ci:
description: "Append [skip actions] to the bump commit so it does NOT trigger workflows."
required: false
type: boolean
default: true
```

- [ ] **Step 2: Make the commit suffix conditional.** In the `Commit Common Bump` step
(`id: commit`), the bump currently runs:

```bash
git commit -am "${{ inputs.commit_message }} [skip actions]"
```

Replace that single line with env-driven, conditional logic (keep everything else in the step —
the `diff-index` guard above it and the rebase-retry push below it — unchanged):

```bash
SUFFIX=""
[ "$SKIP_CI" = "true" ] && SUFFIX=" [skip actions]"
git commit -am "${COMMIT_MESSAGE}${SUFFIX}"
```

And add an `env:` block to that step so the shell reads the inputs safely (place it on the
`Commit Common Bump` step, alongside `id: commit`):

```yaml
env:
SKIP_CI: ${{ inputs.skip_ci }}
COMMIT_MESSAGE: ${{ inputs.commit_message }}
```

> `default: true` makes this byte-for-byte backward compatible — every caller that does not set
> `skip_ci` (upgrade-common, daemons, batch, the merge-main family) keeps committing with
> `[skip actions]`. Booleans render as the strings `"true"`/`"false"`, so `[ "$SKIP_CI" = "true" ]`
> is the correct test.

- [ ] **Step 3: Lint.** `actionlint .github/workflows/php-common-bump.yaml` → expect zero errors.
Also confirm YAML parses: `ruby -ryaml -e "YAML.load_file('.github/workflows/php-common-bump.yaml')"`.

- [ ] **Step 4: Commit, push, open draft PR.**

```bash
git add .github/workflows/php-common-bump.yaml
git commit -m "feat: add skip_ci input to php-common-bump (default true)"
git push -u origin DEVEX-1628-common-bump-build-on-nightly
gh pr create --repo encodium/.github --draft --base main \
--title "DEVEX-1628: optional skip_ci on php-common-bump" \
--body "Adds an optional skip_ci input (default true = current behavior) so nightly common bumps can omit [skip actions] and trigger a build/tag. Backward-compatible: no existing caller changes behavior. Nightly workflows opt in via separate PRs. Refs DEVEX-1628"
```

## Task 2: Merge Task 1 (human review gate)

- [ ] **Step 1:** Reviewer approves and merges the `encodium/.github` PR to `main`. The opt-in
PRs below reference `php-common-bump.yaml@main` and require the `skip_ci` input to exist there.

## Task 3: Pilot opt-in — internal_api

**Files:** Modify `internal_api/.github/workflows/Nightly Common Update.yaml`.

- [ ] **Step 1: Create a worktree.**

```bash
cd ~/dev/internal_api && git fetch origin -q
git worktree add -b DEVEX-1628-nightly-build ~/dev/claude/internal_api-DEVEX-1628 origin/main
```

- [ ] **Step 2: Add `skip_ci: false` to the `with:` block.** The job currently reads:

```yaml
update-common:
uses: encodium/.github/.github/workflows/php-common-bump.yaml@main
with:
php_version: "8.3"
commit_message: "chore: nightly update revolutionparts/common"
secrets:
write_pat: ${{ secrets.REPO_WRITE_PAT }}
packagist_username: ${{ secrets.PACKAGIST_USERNAME }}
packagist_password: ${{ secrets.PACKAGIST_PASSWORD }}
```

Add one line to `with:`:

```yaml
with:
php_version: "8.3"
commit_message: "chore: nightly update revolutionparts/common"
skip_ci: false
```

- [ ] **Step 3: Lint.** `actionlint ".github/workflows/Nightly Common Update.yaml"` → zero errors.

- [ ] **Step 4: Commit, push, open draft PR.**

```bash
git add ".github/workflows/Nightly Common Update.yaml"
git commit -m "ci: build & tag on nightly common bump (skip_ci false)"
git push -u origin DEVEX-1628-nightly-build
gh pr create --repo encodium/internal_api --draft --base main \
--title "DEVEX-1628: build & tag on nightly common bump" \
--body "Nightly common bump now omits [skip actions] so it builds, tags, and deploys to integration. Refs DEVEX-1628"
```

- [ ] **Step 5: Mark ready + merge** (after Task 2 is merged). Then **live-verify** by dispatching
the nightly workflow on `main`:

```bash
gh workflow run "Nightly Common Update.yaml" --repo encodium/internal_api --ref main
# find the run, then read the upgrade-common job log:
gh run list --repo encodium/internal_api --workflow "Nightly Common Update.yaml" --limit 1 --json databaseId,status
```
Expected, **if common changed**: a bump commit on `main` whose message has **no** `[skip actions]`,
and a new `Build` run kicks off (→ new `-main.N` tag → integration deploy). **If common was
already current**: the run logs "No changes to commit" and ends — that is correct; confirm the
suffix logic on the next real common change. Either way the run itself must succeed.

## Task 4: Fan out `skip_ci: false` to the remaining 10 repos

For each repo below: worktree off `origin/main`, add `skip_ci: false` to the nightly workflow's
`with:` block (exactly as Task 3 Step 2 — if a repo has no `with:` block, add one containing
`skip_ci: false`), `actionlint`, commit `ci: build & tag on nightly common bump (skip_ci false)`,
push, open a draft PR titled `DEVEX-1628: build & tag on nightly common bump`, then merge.

- [ ] **`Nightly Common Update.yaml`:** rp_api, catalog_api, license_api, returns-api, accounts-api, webstore, listings-url-service
- [ ] **`nightly-common-update.yaml`** (lowercase filename — confirm the exact path per repo): listings, marketplaces, payments

Per repo:
- [ ] Worktree: `git -C ~/dev/<repo> worktree add -b DEVEX-1628-nightly-build ~/dev/claude/<repo>-DEVEX-1628 origin/main`
- [ ] Edit the nightly workflow `with:` → add `skip_ci: false`
- [ ] `actionlint <nightly-workflow-file>` → zero errors
- [ ] Commit `ci: build & tag on nightly common bump (skip_ci false)`, push, draft PR (`Refs DEVEX-1628`), merge

> Note: the lowercase-`nightly-common-update.yaml` repos (listings, marketplaces, payments) are
> the merge-main family; their nightly bump triggers their own `push: main` build pipeline (build
> + tag per their flow) rather than the `Build.yaml` integration path. listings-url-service is a
> harmless no-op if it has no `push: main` build. All still take the uniform `skip_ci: false` edit.

## Done criteria

- [ ] `php-common-bump.yaml` on `main` has `skip_ci` (default `true`); no existing caller's behavior changed.
- [ ] All 11 nightly common-update workflows pass `skip_ci: false`; every `upgrade-common.yaml` is untouched.
- [ ] Pilot live-verified: a nightly bump with a real common change produces a commit without `[skip actions]` and triggers a build/tag (internal_api).
- [ ] No loop and no merge double-build observed (the `diff-index` guard + untouched merge path hold).
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Nightly common bumps should build & tag (DEVEX-1628)

- **Date:** 2026-06-10
- **Ticket:** DEVEX-1628 (Bug, In Progress) — "Automatic Common bumps are not getting built or deployed to integration"
- **Repos affected:** `encodium/.github` (shared `php-common-bump.yaml`) + 11 service repos (their nightly common-update workflow)

## Problem

`php-common-bump.yaml` commits the `revolutionparts/common` version bump with `[skip actions]`
([line 85](https://github.com/encodium/.github/blob/main/.github/workflows/php-common-bump.yaml)).
That suppresses the `push: main`-triggered `Build.yaml`, so a common bump never produces a
new image tag and the integration environment never receives the updated common.

This interacts with DEVEX-1629: now that `workflow_dispatch` skips `integration-deploy`,
re-triggering a build via dispatch would not deploy either. The only clean way a common bump
reaches integration is for the bump to be a **real push to main** (which builds, tags, and —
being a push — deploys). The bump push is already made with `REPO_WRITE_PAT` (a PAT, which
*does* trigger workflows), so the literal `[skip actions]` text is the only thing stopping it.

## Goal

**Anything that depends on common should receive a new tag and be deployed to integration when
common changes.** Concretely: every **nightly** common bump that actually changes common produces
a new build/tag (and, for repos with an integration pipeline, an integration deploy) — the
ticket's "ideal scenario" — without disturbing the many other `php-common-bump` consumers.

This change covers every common-dependent repo that **has a nightly common-update workflow**
(the 11 below). Common-dependents that lack a nightly workflow (daemons, batch, radmin,
vin_decoder_service) cannot be opted in until one exists; bringing them to full coverage by
adding nightly workflows is a tracked follow-on (see Out of scope).

## Decisions (agreed)

- **Mechanism:** make the suppression configurable; do not remove `[skip actions]` globally.
- **Trigger context:** nightly only. The merge-path `upgrade-common.yaml` keeps skipping, so
normal app merges don't double-build.
- **Scope:** every repo that has a nightly common-update workflow (all such consumers).

## Design

### Change 1 — `php-common-bump.yaml` (shared, one edit)

Add an optional input, **defaulting to today's behavior**:

```yaml
skip_ci:
description: "Append [skip actions] to the bump commit so it does NOT trigger workflows."
required: false
type: boolean
default: true
```

In the `Commit Common Bump` step, append `[skip actions]` only when `skip_ci` is true (pass it
via `env:` to avoid expression-in-shell pitfalls):

```bash
SUFFIX=""
[ "$SKIP_CI" = "true" ] && SUFFIX=" [skip actions]"
git commit -am "${COMMIT_MESSAGE}${SUFFIX}"
```

`default: true` makes this **byte-for-byte backward compatible**: every existing caller that
does not set `skip_ci` (the merge-path `upgrade-common.yaml`, daemons, batch, the merge-main
family, etc.) keeps committing with `[skip actions]` exactly as today. Nothing else in the
workflow changes (checkout, composer install, `composer update revolutionparts/common`, the
`git diff-index` no-change guard, and the rebase-retry push all stay).

### Change 2 — nightly workflows opt in (11 repos)

Each repo's nightly common-update workflow passes `skip_ci: false` to the reusable workflow:

```yaml
update-common:
uses: encodium/.github/.github/workflows/php-common-bump.yaml@main
with:
php_version: "8.3"
commit_message: "chore: nightly update revolutionparts/common"
skip_ci: false # <-- added
secrets:
write_pat: ${{ secrets.REPO_WRITE_PAT }}
packagist_username: ${{ secrets.PACKAGIST_USERNAME }}
packagist_password: ${{ secrets.PACKAGIST_PASSWORD }}
```

**Repos (11):**
- `Nightly Common Update.yaml` (8): rp_api, internal_api, catalog_api, license_api,
returns-api, accounts-api, webstore, listings-url-service
- `nightly-common-update.yaml` (3): listings, marketplaces, payments

The merge-path `upgrade-common.yaml` files are **left unchanged** in every repo.

## Data flow (enabled)

```
nightly cron → composer update revolutionparts/common
→ (only if common changed) commit WITHOUT [skip actions] → push main (REPO_WRITE_PAT)
→ Build.yaml runs on push → tag-and-release cuts a new -main.N tag
→ integration-deploy runs (push event; DEVEX-1629 gate allows push) → integration has fresh common
```

For each repo the effect follows that repo's own `push: main` pipeline: the integration-app
repos build → tag → integration-deploy; the merge-main-family repos (listings, marketplaces,
payments) build + tag per their flow. A repo with no `push: main` build pipeline is a harmless
no-op (the commit simply omits `[skip actions]`).

## Edge cases / safety

- **No loop.** The bump push also re-triggers `upgrade-common` (it is `push: main`); it runs
`composer update`, finds common already current, hits the `git diff-index` guard, commits
nothing, and terminates.
- **Bounded churn.** The `diff-index` guard means a build happens only when common actually
changed — at most one nightly build per repo per common change.
- **No merge double-builds.** Because `upgrade-common` keeps skipping, a normal app merge does
not spawn a second bump-build.
- **Tag mechanics unchanged.** The `chore:` bump commit takes the default patch bump →
`-main.N` prerelease tag, which the Start Release Train can later promote.

## Interactions

- **DEVEX-1630** (build-workflow unification): independent. This change edits *nightly*
workflows + `php-common-bump.yaml`, not `Build.yaml`. It relies only on the push→tag→deploy
behavior the thin callers preserve, so it works before or after that migration. No file
conflict.
- **DEVEX-1629** (integration gate): complementary. A common bump is a real push, so it deploys
via the push path — exactly the behavior the gate intends.

## Out of scope

- Repos without a nightly common-update workflow (daemons, batch, radmin, vin_decoder_service):
no nightly bump exists to opt in. To fully satisfy "anything that depends on common" they would
each need a nightly common-update workflow (and, for integration deploy, a push→integration
build pipeline) added — a tracked follow-on, not part of this change.
- The merge-path (`upgrade-common.yaml`) build-on-bump — deliberately excluded (nightly only).
- The disabled `Nightly Integration Deploy.yaml` placeholder (deploy-latest-tag) — a separate,
complementary idea, not needed for this ticket.