Skip to content

fix(scripts): make .PHONY in package.mk an actual declaration - #4

Merged
myasnikovdaniil merged 1 commit into
mainfrom
fix/package-mk-phony-declaration
Aug 12, 2026
Merged

myasnikovdaniil merged 1 commit into
mainfrom
fix/package-mk-phony-declaration

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Line 2 of scripts/package.mk is .PHONY=help show diff apply delete update image. That is a variable assignment, so make defines a variable called .PHONY that nothing reads, and none of those targets is phony. Line 1 is .DEFAULT_GOAL=help, a real variable where = is correct, which is probably why this went unnoticed.

I measured it both ways in a scratch checkout. With a file named help sitting next to packages/apps/minecraft-server/Makefile, make help on current main prints make: 'help' is up to date. and exits 0 without running the recipe. With the colon in place the recipe runs. Nothing in the repository is named after a target today, so this is latent rather than currently broken.

I changed the list as well. scripts/package.mk defines help show apply diff suspend resume delete check clean, so suspend, resume, check and clean were missing. check is the one that matters most, since it is the prerequisite that keeps show, diff, apply and delete rebuilding. Going the other way, update and image are not defined here at all, neither in scripts/package.mk nor in any of the three package Makefiles. Naming an undefined target in .PHONY creates it empty, so make image would print "Nothing to be done" and exit 0 instead of failing with "No rule to make target". Better to leave them out.

One note on provenance: this file is a byte-for-byte copy of hack/package.mk in cozystack/cozystack, where the same line is being fixed in cozystack/cozystack#3353. The two are identical today, so that change splits them. The target list over there is not automatically right here, and the one in this PR comes from what this repository's own Makefiles define.

Summary by CodeRabbit

  • Chores
    • Replaced the obsolete update and image build commands with suspend, resume, and check commands.
    • Updated available command declarations to reflect the current build workflow.

Line 2 used `.PHONY=`, which is a variable assignment. Make defined a
variable that nothing reads, and none of the listed targets was phony.
The special target needs a colon. Line 1 is `.DEFAULT_GOAL=help`, a
real variable where `=` is correct, which is likely why this went
unnoticed.

Corrected the list to what this file actually defines. `suspend`,
`resume`, `check` and `clean` were missing; `check` is the prerequisite
that keeps `show`, `diff`, `apply` and `delete` rebuilding. Dropped
`update` and `image`, which are defined neither here nor in any package
Makefile: naming an undefined target in `.PHONY` creates it empty, so
`make image` would report nothing to be done and exit 0 instead of
failing with "No rule to make target".

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 70c97709-6d2b-46fe-a37f-63e19d2b60a0

📥 Commits

Reviewing files that changed from the base of the PR and between 1e778fb and e92faec.

📒 Files selected for processing (1)
  • scripts/package.mk

📝 Walkthrough

Walkthrough

The package Makefile updates its .PHONY declaration. It removes update and image, then adds suspend, resume, and check.

Changes

Package targets

Layer / File(s) Summary
Update phony target declarations
scripts/package.mk
The .PHONY declaration removes update and image and adds suspend, resume, and check.

Estimated code review effort: 1 (Trivial) | ~2 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the fix to the .PHONY declaration in scripts/package.mk, which is the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/package-mk-phony-declaration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@myasnikovdaniil myasnikovdaniil left a comment

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.

Checked both sides. On main .PHONY=... lands in the make variable table and the only real .PHONY: in the whole database is generate from the package Makefile. With a file named help next to the Makefile main prints make: 'help' is up to date. and this branch runs the recipe, same for clean.

Target list is right. %-update is the only rule that writes files so excluding it is correct, and nothing in the new list produces a file of its own name.

hack/package.mk upstream gets the same fix in cozystack/cozystack#3353, with a two line comment explaining why .DEFAULT_GOAL = is fine but .PHONY = declares nothing. This repo exists to be copied so worth carrying that comment here too.

No workflows in this repo at all, so nothing here ever ran make and CI could not have caught this one.

@myasnikovdaniil
myasnikovdaniil merged commit df8965d into main Aug 12, 2026
2 checks passed
@myasnikovdaniil
myasnikovdaniil deleted the fix/package-mk-phony-declaration branch August 12, 2026 10:22
Aleksei Sviridkin (lexfrei) added a commit to cozystack/cozystack that referenced this pull request Aug 14, 2026
…t phony (#3353)

## What this PR does

`hack/package.mk` set `.PHONY` with `=` instead of `:`:

```make
.PHONY=help show diff apply delete update image
```

That assigns a variable which happens to be named `.PHONY`; it declares
nothing. `make -p` prints it back among the variables (`.PHONY = help
show diff apply delete update image`) rather than as a special target,
so none of the targets `package.mk` defines was phony in any package
that includes it.

Nothing in the tree collides with those names today, so this is
preventive rather than a fix for present breakage. The failure it
forecloses is quiet: with a directory named `image` beside a package
Makefile, `make image` prints `make: 'image' is up to date.` and exits 0
without building. A file of that name is enough on its own where the
rule has no prerequisites; where it has one, the recipe keeps running
until that prerequisite is shadowed too.

The list changed as well. `suspend`, `resume`, `check` and `clean` are
defined in this file and were missing, and `check` is the one that
matters most, since it is the prerequisite that keeps `show`, `diff`,
`apply` and `delete` rebuilding. `update` and `image` are gone, because
`package.mk` does not define them; the including package Makefile does.
Naming an undefined target in `.PHONY` creates it as an empty target,
turning `No rule to make target` (exit 2) into `Nothing to be done`
(exit 0) wherever the rule is missing. That reaches CI too:
`hack/build-matrix.sh` parses the root Makefile `build:` target and runs
`make -C <pkg> image` per unit, so a package arriving in that list
without an `image:` rule would go from a red job to a green one that
builds nothing.

`.DEFAULT_GOAL` on the line above keeps its `=`. That one is a real
variable, so the assignment form is right there. A comment now says
which of the two lines is which, since they read alike and one of them
just changed shape.

`hack/package-mk-phony.bats` covers the declaration and is picked up
automatically by the `hack/*.bats` glob in `bats-unit-tests`. Five of
its six tests cover `package.mk`: that the declared names are really
phony with a file of each name sitting beside the Makefile; a control
that mutates a copy back to the assignment form and requires the probe
to report up-to-date, so the first cannot pass vacuously; that the
declared list and the defined targets are the same set, checked both
directions; and two pinning the `update`/`image` exclusion, one
requiring the loud failure to survive and one extending the list in a
copy and requiring it to disappear. The loud-failure test pins both the
exit status 2 and the diagnostic. A wrapper that kept make's wording
while returning something else would pass a check on the message alone.

One point decides where the guarantee actually lives. The first test
reads its names from the `.PHONY:` line, so it cannot see a name dropped
from that line at all. The set-equality test is what guards every name's
presence.

One known gap is left in place. The first test decides by matching
make's `is up to date`, which make prints only for a target that has a
recipe, and a recipe-less alias never draws it: with no prerequisite
both forms print `Nothing to be done`, and with a prerequisite that is
itself out of date, which every target in this file is for being phony,
the working form prints that prerequisite's recipe while the broken form
prints `Nothing to be done`. The probe separates neither pair, so such a
name would pass the first test either way. Measured on both shapes, not
assumed. Every target `package.mk` defines has a recipe, so nothing is
uncovered today; the control test does not close the gap either, since
an alias is a defined target and the control requires `is up to date`
from it, which turns it red against the probe rather than against the
alias. Worth closing if an alias is ever added.

One more for whoever edits the suite next: `hack/cozytest.sh` rewrites
every bare `}` at column 0 into `return 0` followed by `}`. That is
aimed at `@test` blocks, but it does not distinguish them from a plain
shell function, so a helper factored out of these tests would silently
become unable to return a non-zero status. Tests 1 and 2 repeat a loop
rather than share one for reasons of their own, but this is the trap
waiting for anyone who merges them.

Two properties of the suite are worth stating, because both are easy to
get wrong in the other direction. The set-equality test extracts the
defined targets with a pattern that accepts a rule naming several
targets at once, so `suspend resume: check` keeps both names in the set;
anchoring the colon to a single name drops every name on such a line,
and for a target nothing else depends on that goes unnoticed. And the
control test probes the targets `package.mk` defines rather than the
names on its `.PHONY:` line, because `is up to date` is only a
meaningful answer for a name that has a rule: a declared-but-undefined
name prints `Nothing to be done` in both the working and the broken
form, so probing it in the control fails against the probe, while the
set-equality test holds the message that names the defect.

Last one, about how the tests find the repo. All six read it as
`repo=$(pwd)`, which assumes the runner starts at the repo root. That
holds for `make bats-unit-tests` and for the invocation the header
documents, so nothing is broken, and the assumption is the ordinary
shape in `hack/` rather than an outlier: about half the bats files there
resolve repo-relative paths against the cwd the same way, several
stating it in their own headers, and this is not even the only one
spelling it with `$(pwd)`. What is worth naming is the failure mode:
started elsewhere, these tests go red with `no '.PHONY:' declaration
found in hack/package.mk`, which reads like a real finding rather than a
wrong directory.

The root `Makefile` had the same defect, and there it had already fired.
`test` was not on its `.PHONY:` line and a `test/` directory sits beside
it, so `make test` printed `'test' is up to date` and exited 0 without
running anything, while `docs/agents/overview.md` advertises that
command as the way to run the full suite. CI never used it: the workflow
calls `test-controllers` and drives e2e out of `packages/core/testing`,
so the cost fell on anyone following the docs by hand. One name on the
declaration closes it, and the suite gained a sixth test that goes red
without it. Every other undeclared target in that file is unshadowed
today, so none of them is reachable the way `test` was, and they are
left alone here. #3709 covers the same class in the four
`packages/core/` Makefiles, which include only `hack/common-envs.mk` and
so are out of reach of this change entirely.

### Downstream repositories

`scripts/package.mk` in cozystack/external-apps-example was a
byte-for-byte copy of `hack/package.mk` (identical sha256 before this
change), carrying the same inert `.PHONY=` line. This PR splits the two
files, and the copy was fixed separately. It landed the same nine names,
and `update` and `image` are absent there for the reason they are absent
here: `scripts/package.mk` does not define them either, and neither does
any Makefile that includes it. What separates the two files now is the
two-line comment added here, and nothing else.

- [ ] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [x]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up: cozystack/external-apps-example#4
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

### Release note

```release-note
NONE
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed task declaration handling so supported commands are correctly
recognized and executed.
* Updated available commands by replacing `update` and `image` with
`suspend`, `resume`, `check`, and `clean`.
* **Tests**
* Added coverage to verify command declarations, prevent regressions,
and ensure invalid or missing commands report errors correctly.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants