feat(emf): model the Resolved Deployment target metamodel in Ecore - #136
Merged
Merged
Conversation
Task 2 transforms into this metamodel and Task 3 generates from it, so it is due for Task 1 with the source metamodel it is the other half of. Nothing existed: `bundles/resolve` and `bundles/render` each held a placeholder package, and the architecture's module table named a target `.ecore` that was not there. The package holds two halves, and that is the point. The first is every decision layer 2 takes, in the words CONTEXT.md gives them. The second is one class per resource family of the project proposal's generated-resources table, each carrying the path it is written to. The production implementation keeps those apart because nothing there reads them together; a model-to-text template reads one model, so here they are one package. That difference is exactly why the parity contract compares the two implementations through dependency edges and generated files rather than through `resolved.json`. No name crosses between the halves. A `WorkloadFile` carries the controller kind and the strategy that spell a Process's `cutover`, and the `cutover` itself stays on the Process, so the template decides nothing. `models/minimal.resolveddeployment` is the hand-written target model, every value of it derivable from `notes.project.yml` and the pinned Platform document and node contract beside it. It is test input and not an oracle: it is what the Acceleo templates are first run against (#94) and what the QVT-Operational transformation must produce (#90), so it is the target half of both tracers before either exists. `DependencyEdges` exports the parity contract's `dependencies.json`, which is the half of resolution both implementations must agree on before either renders. `minimal` holds no edge, so the edge's own shape is proved on a model built in the test: one edge the policy names a peer for, one without. Two of the seven tests tie the model to the tree rather than to itself: the eight paths it assigns are compared with the files actually under `spec/v1/examples/minimal/rendered/`, so a template that writes somewhere else fails here rather than at review. The three pending witnesses move to where they can actually be discharged. REQ-033's reason said there was no Ecore metamodel here to validate against, which this change makes false; what is still missing is a model this implementation *derives*, which is #90. REQ-034 waits on placement resolving against the node contract (#91) and REQ-035 on something rendering (#94).
#87 says the target package is not part of the descriptor, which covers the source metamodel only, and nothing checked it. A target class reaching the descriptor would put this implementation's shape into an oracle the other one has to match, and the two shape layer 2 differently on purpose. The check is by name against the committed descriptor, and it allows exactly three: `Cutover`, `Match` and `DurabilityClass` are the source metamodel's own vocabularies, carried into the target package under the same names because they mean the same thing.
Shape
CoverageBaseline:
This pull request changed no covered line. |
CodeQL reported three `java/local-variable-is-never-read` findings against `ResolvedDeploymentTest`, on locals every one of which is passed to `assertThat`. The cause is in the same log: buildless extraction failed to get a dependency graph from Maven, and `.github/codeql/codeql-config.yml` excludes `**/target/**`, where the metamodel's generated Java lives. A local whose only read sits inside an expression over an unresolved type reads as never read. `DescriptorTest` never trips this because it works off the committed JSON rather than a generated package. Filtering the rule was the other way out and it is worse: the rule is right in general, and a repository-wide exclusion to accommodate one file's shape hides the unused locals it exists to find. The three locals carried no meaning the assertion did not already carry, so they are inlined, which is the shape the Java test beside this one already uses. The descriptor is the exception: it is read once per classifier inside a lambda, so it is a field rather than a local, with a comment naming why.
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #87. Part of #78.
What this branch does
Task 2 transforms into the Resolved Deployment metamodel and Task 3 generates from it, so it is due for Task 1 alongside the source metamodel it is the other half of. Nothing existed:
bundles/resolveandbundles/rendereach held a placeholdernotes.ecore, and the module table named a target.ecorethat was not in the tree.bundles/metamodel/model/resolved-deployment.ecore, 35 classifiers in one package. Its Java is generated intotarget/by a second MWE2 workflow, the way the source metamodel's already is, and is left out of formatting, coverage and mutation on the same rule.plugin.xmlregisters the package, so an examiner's Eclipse import resolves it.models/minimal.resolveddeployment, the hand-written target model. Every value of it is derivable fromnotes.project.ymland the pinned Platform document and node contract beside it. It is test input and not an oracle: it is what the Acceleo templates are first run against (Tracer bullet for Task 3: render the minimal case with Acceleo from its hand-written target model #94) and what the QVT-Operational transformation must produce (Tracer bullet for Task 2: resolve the minimal case with QVT-Operational #90), so it is the target half of both tracers before either exists.DependencyEdges, the export of the parity contract'sdependencies.json: the consumer Process, the provider Application and Surface, the address the consumer is given, and the peers the policy allows.The decisions
The package holds two halves, and that is the point. The first is every decision layer 2 takes, in the words
CONTEXT.mdgives them. The second is one class per resource family of the project proposal's generated-resources table, each carrying the path it is written to. The production implementation keeps those apart because nothing there reads them together; a model-to-text template reads one model, so here they are one package. That difference is exactly why the parity contract compares the two implementations through dependency edges and generated files rather than throughresolved.json.No name crosses between the halves. A
WorkloadFilecarries the controller kind and the strategy that spell a Process'scutover, and thecutoveritself stays on the Process. The template decides nothing, which is the layer rule holding one level further down than the chapter states it.The target package stays out of the descriptor, and that is now checked rather than asserted. A target class reaching the descriptor would put this implementation's shape into an oracle the other one has to match. The check allows exactly three names through:
Cutover,MatchandDurabilityClassare the source metamodel's own vocabularies, carried over because they mean the same thing.What the tests hold
Eight, and two of them tie the model to the tree rather than to itself: the eight paths it assigns are compared with the files actually on disk under
spec/v1/examples/minimal/rendered/, so a template that writes somewhere else fails here rather than at review.minimalholds no dependency edge, which is the point of that case, so the edge's own shape is proved on a model built in the test: one edge the policy names a peer for, and one that resolves to an address with no peer of its own.The pending witnesses move
REQ-033's reason said there was no Ecore metamodel here to validate against. This change makes that false, so it would have become a lie on merge. What is still missing is a model this implementation derives, which is #90. REQ-034 waits on placement resolving against the node contract (#91), and REQ-035 on something rendering (#94). All three stay owed; none is quietly discharged.
Verification
./mvnw -B -ntp verifyfromemf/exits 0 locally: 53 tests, the jacoco floor at 1.00 and pitest's mutation threshold both met. Rootnpm run verifygreen at 782 tests, 35 ledger rows, 99.2% statements.Two failures were caught locally before anything was pushed, which is worth recording because the previous branch learned it the hard way: spotless formatting, and the jacoco floor, because the edge-building path never ran against a case that has no edges.