and template Implements the finalize stage infrastructure for HoneyBiscuitWorkshop: - New finalize module with config, error, event, plugin, stage, and template submodules - Plugin system supporting internal (webhook, mail, satori, in-site) and external plugins - FinalizeConfig schema with version validation for finalize.yml - Add glob, duration-str, lettre dependencies to workshop-baker - Expand project documentation (clarification.md, description.md) - Update .gitignore and fix bake.rs pipeline_functions access BREAKING CHANGE: Not a buildable version!
38 KiB
Updated Questions & Doubts
A. Plugin System
-
falliblevscritical- You changed from
critical: falsetofallible: false - Is
fallible: truethe same ascritical: false? (Double negative situation) - Consider:
fail_build_on_error: true/falseis clearer
- You changed from
-
Plugin URI Format
git::github.com/user/repo@main/1234abcd- Is
mainthe branch and1234abcdthe commit? - What if branch and commit don't match? Which takes precedence?
- Are other protocols supported? (
hg::,http::,file::?)
-
Plugin Configuration Scope
- In
plugin:section, you definehost,user,token - In
publish:, you defineimage: "docker.io/user/image:tag" - Are these merged? Overridden?
- What if
publish.docker-push.imagediffers fromplugin.docker-push.host?
- In
-
Multiple Plugin Implementations
- Can
docker-push:have multiple URIs under it?
docker-push: "git::github.com/user/plugin-a@main": ... "git::github.com/user/plugin-b@main": ... # Allowed? - Can
B. Notification Priority
-
Fallback Semantics
- Comment: "inter-group falling back"
- Does group
1run only if group0fails? - Or does group
1run after group0succeeds? - Or both groups run, but
1is lower priority for delivery?
-
Parallel Within Group
- If
webhooksucceeds butsatorifails in group0, what happens? - Does group
1get triggered because of partial failure? - Or is group
0considered "succeeded" if at least one succeeds?
- If
-
Notification Failure vs Build Failure
- If all notifications fail, does the build fail?
- Is there a global
falliblefor notifications?
C. Stage-Based Notifications
-
on_finish_ofIntegrationon_finish_of: stage: "prebake.ready"- How does this integrate with
PrebakeStageenum from codebase? - Current stages:
Bootstrap -> Ready(from AGENTS.md) - Are all stages valid? (
prebake.bootstrap,bake.complete,finalize.*?)
- How does this integrate with
-
on_finish_ofvson_success/on_failure- Can these coexist on the same notification?
- Does
on_finish_oftrigger regardless of success/failure? - Is there
on_start_offor "notify when stage begins"?
-
Stage Timing
- When
on_finish_of: prebake.readyfires, is{{ build.status }}available? - Or is build status only meaningful after
bakestage?
- When
D. Artifact System
-
Auto-Generated ID
id: "<SOME_ARTIFACT_ID>" # Generated by Pipeline UUID & Path when not given- Is
idoptional now? Can you omit it entirely? - If auto-generated, how do you reference it in
publish? - Or is
publishalways bypathmatch, notid?
- Is
-
Empty Path Semantics
path: "" # Implies non-directory artifact- What is a "non-directory artifact"?
- Is this for metadata-only artifacts?
- Or does empty path mean "use default output path from bake.sh"?
-
Retention Duration Parsing
"7d",604800(seconds?),"168h"- are these equivalent?- What's the canonical format? Should there be validation?
- Consider standardizing: ISO 8601 duration (
P7D)?
-
Compression
dirOptioncompression: "zstd" # gzip|none|dir allowed- What does
compression: "dir"mean? No compression, keep as directory? - Should this be
"directory"or"raw"for clarity?
- What does
E. Template Variables
-
Variable Availability by Stage
{{ build.duration }}- available atprebake.ready? (Probably not){{ build.status }}- what values?"success"|"failure"|"running"?- Should there be stage-specific variable namespaces? (
{{ prebake.* }},{{ bake.* }})
-
Target Namespace
{{ target.group_id }}- where is this defined?- Is
targetthe notification target, or build target environment? - Can users define custom
{{ target.* }}variables?
F. Schema & Validation
-
Schema Field Purpose
schema: "default" schema: "custom"- What does
defaultschema do? Built-in payload format? - Is
customrequired whenon_*templates are provided? - Can you use
schema: "slack"or other named schemas?
- What does
-
Version Compatibility
version: "0.0.1"- suggests breaking changes expected- How will version migrations work?
- Should there be a
schema_versionseparate from implementation version?
G. Missing Features (Intentional?)
-
Conditional Artifacts
- Can artifacts have conditions like bake.sh's
@if()? - E.g., only publish docker image on
mainbranch
- Can artifacts have conditions like bake.sh's
-
Artifact Dependencies
- Can one artifact depend on another?
- E.g., "publish only if artifact A was successfully uploaded"
-
Cleanup Granularity
cleanup: policy: "auto"- What other policies exist?
"manual"?"on_failure"? - Is cleanup per-artifact or global?
- What other policies exist?
-
Timeouts & Retries for Notifications/Plugins
- No timeout/retry config visible
- Are these inherited from bake.sh decorators?
- Should plugins have their own retry logic?
Summary of Design Gaps
| Area | Missing/Unclear |
|---|---|
| Plugin | Config merging, multiple URIs, protocol support |
| Notification | Fallback semantics, failure propagation, stage integration |
| Artifact | Auto-ID referencing, empty path use case, conditions |
| Template | Variable availability by stage, custom namespaces |
| Schema | default/custom behavior, extensibility |
| Error Handling | Timeouts, retries, failure escalation |
What would you like to clarify or iterate on?
User
- fallible:true = critical: false, of course. This concept is the same as bake.sh
- if no according commit/tag in the branch, it means nothing and fail. Other protocols will be supported but some are sonner(file) and some are later(hg)
- Caller than Definition: parameters in publish overrides plugin No way could user success if image.host != host. host is only for authentication usage. image.host could be emitted if host given.
- not allowed. key is unique. 5/6/7. fallback explanation: (notification->no) no.0 starts all at once if one method in no.0 fails, no.1 is active (then no.2,...) the failure of no.0 will be part of no.1, this means baker will wait for no.0 to finish and then no.1 fallible could apply here
- for prebake/finalize, second field is static, for bake, second field is dynamic according to bake.sh / Function(class) validity checks upon execution, maybe early-checked at future
- yes maybe a condition system required
- Still WIP
- ID is optional and will be generated by system publish doesn't reference artifact, artifact reference publish
- Docker image as an example future url:// based path, such as docker://docker.io/user/image:tag adopted from RedoxOS, however too advanced to promote.
- equivalent. validation required. default unit is second
- dir will be used for software repo: they need structued directory than single .tar
- WIP
- WIP
- default will be defined by (internal) plugins custom required for on* schema could be defined in notification block for unified use
- We'd expect not to change schema after 1.0, though it's impossible migration system built-in for new version
- yes
- yes
- WIP
- WIP
Assistant (Sisyphus (Ultraworker) · GLM-5 · 57.4s)
Synthesized Design Understanding
Based on your clarifications, here's the refined design:
Plugin System
plugin:
<logical-name>: # Unique key
"<protocol>::<uri>@<branch>/<commit>":
# Auth/config parameters (can be overridden in publish)
host: "docker.io"
user: {{ dockerhub.user }}
token: {{ secret.dockerhub.token }}
fallible: false # Same semantics as bake.sh @fallible
host= authentication endpoint onlypublish.<name>.imagecan omit host if pluginhostdefined
Notification Flow
Priority 0: [webhook, satori] ──parallel──┬──► if ALL fail ──► Priority 1: [mail]
│
└──► wait for completion before next group
- Within group: parallel
- Across groups: sequential fallback on failure
falliblecan apply per notification method
Artifact Publishing
artifact:
- path: "" # Empty = URL-style artifact (docker://, etc.)
publish:
<plugin-name>:
# Override plugin params here
image: "docker.io/user/image:tag" # host optional if plugin defines it
- Artifact pushes to publish, not publish pulls artifact
- ID auto-generated when omitted
Follow-Up Questions
A. Plugin Config Merging
-
Deep vs Shallow Merge
plugin: docker-push: host: "docker.io" auth: user: "admin" token: "xxx" publish: docker-push: auth: user: "override-user" # Does this merge {user, token} or replace entire auth?- Is merge deep (nested objects merge) or shallow (replace entire key)?
-
Required vs Optional Plugin Params
- If plugin defines
hostanduseras required, but publish omitsuser... - Is there a schema for plugin to declare required params?
- Or is validation purely "fail at runtime if missing"?
- If plugin defines
B. Notification Fallback Edge Cases
-
Partial Failure Within Group
Priority 0: webhook ✓, satori ✗- Is group 0 considered "failed" if any method fails?
- Or only if all methods fail?
- This determines whether priority 1 triggers
-
Timeout Interaction with Fallback
0: webhook: url: "..." timeout: 30s # Hypothetical 1: mail: ...- If webhook times out at 30s, does mail immediately start?
- Or does system wait for webhook's internal retry logic first?
-
Fallback with
fallible0: webhook: fallible: true 1: mail: fallible: false- If webhook fails but is
fallible: true, does mail still trigger? - Or does
fallible: truemean "failure doesn't trigger fallback"?
- If webhook fails but is
C. Stage-Based Notifications
-
Stage Naming Convention
prebake.ready- static namebake.build- function name from bake.sh?- What about
finalizestages?finalize.artifact?finalize.notification? - Are there built-in stages that always exist?
-
Multiple
on_finish_ofTriggerssatori: on_finish_of: - stage: "prebake.ready" - stage: "bake.test"- Can a notification trigger at multiple stages?
- Or is it one
on_finish_ofper notification definition?
-
on_success+on_finish_ofCombinationsatori: on_finish_of: stage: "prebake.ready" on_success: | # Build success, not stage success?- If
on_finish_of: prebake.readyfires but build eventually fails... - Does
on_successcontent get used oron_failure? - Or does
on_finish_ofhave its owncontentonly?
- If
D. Artifact Path Schemes
-
URL Scheme Examples
path: "docker://docker.io/user/image:tag" path: "s3://bucket/key" path: "ghcr://user/repo:tag"- Are these the intended schemes? Or something else?
- Does each scheme map to a specific plugin automatically?
-
Mixed Path Types in Single Config
artifact: - path: "/workspace/output.tar.gz" # File - path: "" # Docker image (how to specify image name?) - path: "docker://docker.io/img:tag" # Explicit scheme- When
path: "", where does the image name come from? Only frompublish.docker-push.image? - Can you have
path: ""withoutpublish? (Just store locally?)
- When
E. Compression & Directory Artifacts
dirCompression + Uploadartifact: - path: "/workspace/output/" compression: "dir" publish: some-plugin: ...- When uploading a
dirartifact, does plugin receive:- The directory path?
- A tarball created on-the-fly?
- Individual files?
- How does
docker-pushhandlecompression: "dir"?
- When uploading a
F. Conditional System (Planned)
- Condition Syntax
artifact: - path: "..." publish: docker-push: image: "..." if: "${BUILD_BRANCH} == 'main'" # Hypothetical- Will conditions use shell-style
$VAR? - Or template-style
{{ env.BRANCH }}? - Or bake.sh-style
@if(WS_PIPELINE_ARCH == amd64)?
- Will conditions use shell-style
G. Error Handling
-
Plugin Execution Failure
artifact: - publish: docker-push: fallible: true another-plugin: fallible: false- If
docker-pushfails (fallible), doesanother-pluginstill run? - Or do all plugins for an artifact run in parallel regardless?
- If
-
Artifact Collection Failure
- What if
path: "/workspace/target/release/*"matches nothing? - Is this a build failure or silently skipped?
- Is there
on: ["missing"]for handling missing artifacts?
- What if
Design Consistency Observations
Alignment with Existing Patterns
| Concept | prebake.yml | bake.sh | finalize.yml |
|---|---|---|---|
| Fallible | - | @fallible |
fallible: bool ✓ |
| Timeout | - | @timeout(30) |
WIP |
| Retry | - | @retry(3, 5) |
WIP |
| Parallel | - | @parallel |
Intra-group parallel ✓ |
| Conditional | - | @if(cond) |
Planned ✓ |
| After/Deps | hooks.early/late |
@after(func) |
Priority groups ✓ |
Potential Inconsistencies
-
retensiontypo - Should beretention -
Duration format inconsistency
- prebake.yml:
ttl_days: 30 - finalize.yml:
retension: "7d" - Consider standardizing to one format
- prebake.yml:
-
Plugin reference style
- bake.sh:
@after(func_name)- direct reference - finalize.yml:
publish: docker-push:- nested config - Both valid, just noting the difference
- bake.sh:
What would you like to explore next?
User
- any
- overrides "auth" than "user"
- checker cries. checked implemented in plugin
- same as 3. timeout = single failure, not group failure
- fallible of a stage will stop error propagation, thus leaving 1 alone. for last stage, fallible means no other method of notification. (if none of notification FULLY works, system-level fallback, like user email via system(SHOULD be well-configured because user creation relies on this) and in-site notification)
- WIP cuz finalize itself is our plan
- yes, logical expression may be introduced
- every condition have its own content
- not quite planned by now. not completely correct? bake.sh shoudn't upload content to S3 and let finalize to fetch it for artifact however maybe we don't prohibit this. users may do everything in bake and skip finalize.
- path:none + publish: none means nothing, because the build environment will soon be destroyed if it's saved externally (eg. via docker socket), then it shoudn't exist as artifact
- plugin receive a prefetched directory at plugin workspace, this is ensured by rsync. docker-push should ignore compression (or maybe prohibit it)
- WIP
- if one fails but fallible, others will run as expected
- matches nothing invalidates artifact content, but plugin may handle "none" as content
- retention IS typo.
- we haven't implemented prebake.cache thus they might be unified
Assistant (Sisyphus (Ultraworker) · GLM-5 · 54.4s)
Updated Design Understanding
Notification Fallback (Clarified)
Priority 0: [webhook ✗, satori ✗] ──► ANY fails triggers fallback
↓
Priority 1: [mail]
↓
Priority N: [system-email, in-site] ──► Ultimate fallback (system-level)
fallible: trueat group N = stop propagation, don't trigger group N+1fallible: trueat last defined group = no further notification attempts- System-level fallback exists outside user config (configured at user creation)
Plugin Execution
Artifact Collection (rsync to plugin workspace)
↓
Plugin receives: prefetched directory
↓
docker-push: ignores/prohibits compression: "dir"
Config Override Behavior
plugin:
docker-push:
auth: # ENTIRE key replaced
user: "default"
token: "xxx"
publish:
docker-push:
auth:
user: "override" # { user: "override" } - token LOST
Remaining Questions
A. Plugin Workspace & File Handling
-
Plugin Workspace Location
- Where is the plugin workspace?
/workspace/.plugins/docker-push/? - Is this workspace shared across all artifacts using same plugin?
- Or isolated per artifact?
- Where is the plugin workspace?
-
Large Artifact Handling
- If artifact is 10GB, does rsync complete before plugin starts?
- Or does plugin stream from rsync?
- Is there a size limit/timeout for rsync?
-
Plugin Working Directory
- Does plugin receive
pathas-is, or resolved absolute path? - Example:
path: "/workspace/target/release/*"→ plugin sees/workspace/.plugins/docker-push/release/?
- Does plugin receive
B. Artifact Validation
-
Glob Expansion Timing
path: "/workspace/target/release/*"- When is glob expanded? Config load? Execution time?
- If expanded at load time to 3 files, is it 3 artifacts or 1 artifact with 3 files?
-
Artifact ID Generation
- Format:
pipeline-uuid-path-hash? Or something else? - Is ID deterministic (same path = same ID) or random?
- Format:
C. Publish Execution Order
- Multiple Plugins for One Artifact
artifact: - path: "/workspace/output.tar.gz" publish: docker-push: image: "app:latest" s3-upload: # Second plugin bucket: "my-bucket"- Execution order: sequential? parallel? configurable?
- If
docker-pushfails, doess3-uploadrun?
D. Notification Content Templates
-
Condition-Content Mapping
satori: on_finish_of: stage: "prebake.ready" content: "Prebake done" on_success: content: "Build succeeded" on_failure: content: "Build failed"- If
prebake.readyfinishes but build later fails... - Does
on_finish_ofsend atprebake.readytime? - Then
on_failuresends at build end? - Both messages sent, right?
- If
-
Template Variable Scope
on_finish_of: stage: "prebake.ready" content: "{{ build.status }}" # Not available yet?- What happens when variable isn't available at that stage?
- Empty string? Error?
"unknown"?
E. Error Recovery
-
Plugin Error Reporting
- How does plugin report errors back to baker?
- Exit code? JSON output? Structured log?
- Is there a plugin API contract?
-
Retrying Individual Methods
notification: 0: webhook: retry: 3 # Hypothetical retry_delay: 5s- Will retry be per-method, per-group, or global?
- Or should plugins handle their own retry?
F. System-Level Fallback
-
System Notification Configuration
- Where is system email configured?
- In prebake.yml? baker config? System-wide config?
- What if system email also fails?
-
In-Site Notification
- Does this mean a web UI notification?
- Stored in database? Shown in baker dashboard?
G. Typo & Format Fixes
-
Proposed Fixes
artifact: - path: "/workspace/output.tar.gz" retention: "7d" # Fixed typo compression: "zstd" on: - success- Confirm:
retension→retentionfor final version?
- Confirm:
-
Duration Format Unification
# Option A: String with unit (current) retention: "7d" # Option B: Structured retention: days: 7 # Option C: ISO 8601 retention: "P7D"- Preference for consistency with future
prebake.cache?
- Preference for consistency with future
H. Edge Cases
-
Empty Notification Group
notification: 0: {} # Empty group? 1: mail: ...- Is empty group valid? Ignored?
- Or validation error?
-
Circular Plugin Reference
- Can plugin A's output be used as plugin B's input?
- Example: docker-push → image scanner plugin
- Or should this be a single composed plugin?
Summary: Design Maturity
| Component | Status | Notes |
|---|---|---|
| Plugin system | ✅ Clear | URI, override, fallible defined |
| Notification priority | ✅ Clear | Fallback semantics defined |
| Notification stages | ⚠️ WIP | on_finish_of structure defined, finalize stages TBD |
| Artifact collection | ✅ Clear | rsync to plugin workspace |
| Artifact publishing | ✅ Clear | Sequential/parallel WIP |
| Conditional system | ⚠️ WIP | Planned |
| Error handling | ⚠️ WIP | Timeout/retry TBD |
| System fallback | ✅ Clear | Email + in-site notification |
| Typo fix | ✅ Confirmed | retention |
| Duration format | ⚠️ TBD | Unify with prebake.cache |
What's the next aspect to design or clarify?
User
- defined by plugin itself
- rsync before plugin, UNLESS specified by plugin (maybe someone implements more robust method) (not completely rsync thou, hard link/filesystem features may be used)
- as 1
- glob->RE, checked when loading, compiled at running, 1s for total limitation(RE compile+match). one path means one artifact element
- hash of PUID+PATH, maybe MD5 is enough
- SHOULD be parallel, fails: see fallible
- both sent, one first.
- WIP as variable system not defined, just as example. build.status could mean "bake.fetch:3%" or "prebake:ready!" here.
- plugin is shell scripts/ rhai scripts. Via API/CLI(or, function, for shell) and exit-code. Log will be captured but not as evidence
- retry per method
- system email contigured via Web+Server(not started) If system email also fails: via in-site notification If none works: we admit we have no way to notify user. We give up. Admin will receive this message if the configures to do so.
- WebUI, stored in DB, in baker dashboard.
- we'll fix it
- ISO 8601 sounds good, P could be emitted because only period supported. Who'd like to hard-code specific time into static config? Maybe there is.
- 0 should be eliminated and email evolve to 0 every field could lie in any priority, thus webhook could lie in 999 treat as a failure if 0 is none
- make plugin callable w/o artifact chain loading might be reconsidered, because push and check may share the same INPUT than OUTPUT
Assistant (Sisyphus (Ultraworker) · GLM-5 · 54.3s)
Final Design Synthesis
Artifact Collection Flow
Glob Path → RE Compile (load) → Match (run, 1s timeout) → One artifact per match
↓
Hash(PUID + PATH) → MD5 as ID
↓
Hard-link/rsync to plugin workspace (plugin-defined location)
↓
Plugin executes (shell/rhai)
↓
Exit code = success/failure
Notification Flow (Final)
Priority 0: [webhook, satori] ──parallel──► ALL succeed = done
│ │
│ └── ANY fails ──► Priority 1
│ │
▼ ▼
retry per method [mail] ──► ...
│
▼
System fallback: in-site DB
│
▼
Give up → Admin notification
Plugin Architecture
Plugin = Shell script | Rhai script
└── Communicates via: API/CLI/function calls + exit code
└── Log captured (informational, not evidence)
└── Workspace location: plugin-defined
└── File transfer: hard-link/rsync by default, plugin can override
└── Callable without artifact (standalone execution)
Duration Format
retention: "7D" # ISO 8601, P omitted
retention: "168H" # Hours also valid
retention: "604800" # Seconds (no unit)
Final Questions
A. Plugin Without Artifact
-
Standalone Plugin Definition
plugin: health-check: # No artifact input "git::github.com/user/health-plugin@main": endpoint: "https://api.example.com" # How is it invoked?- Where does standalone plugin get invoked? In
notificationblock? - Or separate
finalize.plugins:section? - Example syntax?
- Where does standalone plugin get invoked? In
-
Standalone Plugin Output
- Does standalone plugin produce anything?
- Or purely side-effect (HTTP call, etc.)?
B. Plugin Chain (Reconsidered)
- Shared Input Pattern
Artifact A ──► docker-push ──► (image in registry) │ └──► image-scanner ──► (scan results) (same input: artifact A, not docker-push output)- Both plugins receive same artifact input?
- Configuration example:
artifact: - path: "/workspace/image.tar" publish: docker-push: { image: "app:latest" } image-scanner: { severity: "high" } # Same input, parallel?
C. Priority Group Flexibility
-
Non-Sequential Priority Numbers
notification: 0: webhook: ... 999: mail: ...- Is 999 valid? Or auto-renumbered to 1?
- What about gaps:
0,5,10? - Integers only, or can use named priorities? (
high,low?)
-
Empty Group Handling
notification: 0: {} 1: mail: ...- Result:
0eliminated,mailbecomes0? - Or: validation error at config load?
- Result:
D. Plugin Language Details
-
Rhai vs Shell Choice
- Is this a plugin-level declaration?
plugin: my-plugin: "git::..." runtime: "rhai" # or "shell"?- Or detected by file extension? (
plugin.rhaivsplugin.sh)
-
Plugin API Contract
- Shell: environment variables? CLI arguments? Stdin?
- Rhai: injected functions/objects?
- Example of plugin receiving artifact path and config?
E. Build Status Progress
- Progress Reporting
build.status = "bake.fetch:3%" build.status = "prebake:ready!"- Is this a real-time string that updates?
- Or structured:
{{ build.stage }}+{{ build.progress }}? - How does plugin/notification read live progress?
F. Configuration Validation
-
Early vs Late Validation
- Glob → RE: checked at load time
- Plugin existence: checked at load or run?
- Secret reference (
{{ secret.xxx }}): checked at load or run?
-
Schema Validation Scope
- Is there a JSON Schema for finalize.yml?
- Or just Rust struct deserialization with custom validators?
G. Security Considerations
-
Plugin Trust Model
- Plugins are arbitrary shell scripts from Git repos
- How is trust established?
- Allowlist? Signature verification? User confirmation on first use?
-
Secret Exposure to Plugins
{{ secret.dockerhub.token }}- passed to plugin how?- Environment variable? File? CLI arg (visible in ps)?
- Plugin sandbox/isolation?
Design Maturity (Final)
| Component | Status | Open Items |
|---|---|---|
| Plugin execution | ✅ | Trust model, secret passing |
| Plugin standalone | ⚠️ | Invocation syntax TBD |
| Plugin chain | ✅ | Shared input pattern confirmed |
| Artifact collection | ✅ | Hash ID, glob→RE |
| Notification priority | ✅ | Empty group handling |
| Notification fallback | ✅ | System fallback chain defined |
| Plugin runtime | ⚠️ | API contract details |
| Progress reporting | ⚠️ | Variable system WIP |
| Duration format | ✅ | ISO 8601, P omitted |
| Validation | ⚠️ | Schema definition |
| Typo | ✅ | retention confirmed |
Is there anything else to clarify, or should we proceed to implementation planning?
User
- WIP
- MAY produce anything, may become another artifact however this is weird, users should do this in bake stage than finalize
- plugins could own TOKEN/LOCK and release upon finish eg docker-push acquires "IMAGE." token. image-scanner could start in parallel but soon be paused for no token available.
- integers only, 0~INT_MAX, we don't limit if someone writes 2147483647, either a. as long as they are happy or b. rejected by their superior
- mail should become 0 however we don't do this we warn about empty group
- runtime could be automatically detected
- shell: via CLI and VAR rhai: WIP
- stage maybe means LAST FINAL state, progress is dynamic.
- by design bakerd should fetch plugin as long as they're ready (git/http at prebake stage and file at finalize.begin) assume nothing changed git/http when baking because they require hash.
Assistant (Sisyphus (Ultraworker) · GLM-5 · 14.0s)
User
- WIP
- MAY produce anything, may become another artifact however this is weird, users should do this in bake stage than finalize
- plugins could own TOKEN/LOCK and release upon finish eg docker-push acquires "IMAGE." token. image-scanner could start in parallel but soon be paused for no token available.
- integers only, 0~INT_MAX, we don't limit if someone writes 2147483647, either a. as long as they are happy or b. rejected by their superior
- mail should become 0 however we don't do this we warn about empty group
- runtime could be automatically detected
- shell: via CLI and VAR rhai: WIP
- stage maybe means LAST FINAL state, progress is dynamic.
- by design bakerd should fetch plugin as long as they're ready (git/http at prebake stage and file at finalize.begin) assume nothing changed git/http when baking because they require hash.
- WIP
- allow ANY plugin cus plugin is in environment(docker/VM usually) bare-metal plugin requires more work and permission (PIP:Pipeline Implicit Parameters)
- Via baker. Isolation = how baker (and the whole bake process) is isolated.
Assistant (Sisyphus (Ultraworker) · GLM-5 · 61.4s)
New Discovery: Plugin Token/Lock System
This is a significant design element! Let me clarify:
Plugin Coordination via Tokens
Artifact A ──► docker-push ──► Acquire "IMAGE.docker.io/user/app"
│ │
│ └── Holds token until done
│
└──► image-scanner ──► Wait for "IMAGE.docker.io/user/app"
│
└── Resumes when token released
Follow-Up Questions
A. Token/Lock System
-
Token Naming Convention
"IMAGE.<URL>"- is this a convention or built-in?- Can plugins define custom token names? e.g.,
"DEPLOY.production" - Is there a reserved namespace? (e.g.,
"SYSTEM.*")
-
Token Scope
artifact: - path: "/workspace/app.tar" publish: docker-push: image: "docker.io/user/app:v1" # Implicitly acquires "IMAGE.docker.io/user/app:v1"? - path: "/workspace/app.tar" # Same artifact, different tag publish: docker-push: image: "docker.io/user/app:latest" # Different token? "IMAGE.docker.io/user/app:latest"?- Is token per image URL? Per artifact? Per plugin instance?
- How does system know what token to acquire?
-
Token Declaration
- Does plugin declare required tokens in its schema?
- Or baker infers from plugin config (e.g.,
imagefield)?
# In plugin definition? plugin: docker-push: "git::...": tokens: - "IMAGE.{{ config.image }}" # Template? -
Deadlock Prevention
artifact: - publish: plugin-a: token: "RESOURCE.X" # Acquires X, then Y plugin-b: token: "RESOURCE.Y" # Acquires Y, then X- Does baker detect potential deadlocks?
- Or is this user's responsibility?
-
Token Timeout
- If docker-push hangs forever, image-scanner waits forever?
- Is there a token acquisition timeout?
- Or inherit from plugin's
timeoutsetting?
B. Plugin Fetch Timing
-
Prebake-Stage Plugin Fetch
prebake: fetch git/http plugins bake: (assume plugins unchanged) finalize.begin: fetch file:// plugins- Where are fetched plugins stored?
/workspace/.plugins/? - Are they verified against hash before execution?
- Where are fetched plugins stored?
-
file:// Plugin Path
plugin: my-plugin: "file:///workspace/my-plugin.sh":file://means plugin is already in build environment?- Or on baker server (different machine)?
- How does this work with Docker isolation?
C. Plugin Runtime Detection
- Detection Logic
"file:///plugin.sh" → shell "file:///plugin.rhai" → rhai "git::github.com/user/plugin@main/plugin.sh" → shell- Detected by file extension in URI?
- What if no extension? Default to shell?
- Can user override detection?
plugin: my-plugin: "file:///plugin.bin": runtime: "shell" # Force shell
D. Shell Plugin Interface
-
CLI Arguments Structure
# Example invocation? ./plugin.sh \ --artifact-path "/workspace/.plugins/docker-push/..." \ --config '{"image": "docker.io/user/app:latest"}' \ --secret-token "xxx"- What arguments are passed?
- Config as JSON string? Environment variables? Both?
-
Environment Variables
ARTIFACT_PATH="/workspace/.plugins/..." PLUGIN_CONFIG_IMAGE="docker.io/user/app:latest" SECRET_DOCKERHUB_TOKEN="xxx"- What's the naming convention?
PLUGIN_CONFIG_*for config?SECRET_*for secrets?
E. Progress Reporting
-
Progress Variable Semantics
build.status = "bake.fetch:3%"- Is this a single string variable that updates?
- Or structured:
build.stage = "bake.fetch",build.progress = 3? - Can plugin/notification access
{{ build.progress }}?
-
Real-Time Access
- Can notification's
on_finish_ofaccess live progress? - Or only "last final state" at the moment of trigger?
- Can notification's
F. Bare-Metal Plugin Security (PIP)
-
Pipeline Implicit Parameters (PIP)
- What does this include?
- Permission flags? Sandboxing options?
- Example config?
-
Bare-Metal Plugin Isolation
environment: builder: "baremetal" finalize: plugin: docker-push: ... # Needs special handling?- How does bare-metal differ from Docker/VM for plugins?
- What restrictions apply?
Summary: Token System Design (Emerging)
# Hypothetical explicit token declaration
plugin:
docker-push:
"git::...":
tokens:
acquire: ["IMAGE.{{ image }}"] # Acquired on start
release: ["IMAGE.{{ image }}"] # Released on finish
# Or implicit from 'image' field?
artifact:
- path: "/workspace/app.tar"
publish:
docker-push:
image: "docker.io/user/app:latest"
# System infers: acquire "IMAGE.docker.io/user/app:latest"
image-scanner:
image: "docker.io/user/app:latest"
# System infers: wait for "IMAGE.docker.io/user/app:latest"
# Or explicit:
wait_tokens: ["IMAGE.docker.io/user/app:latest"]
This is a powerful coordination mechanism! Should tokens be:
- Implicit: Inferred from plugin config fields
- Explicit: Declared by plugin author in plugin schema
- Mixed: Implicit with override capability
What's your preference?
User
Too many questions lol. Maybe answering after actually working on finalize. Lock/Token is managed by system so dead-lock detection should be easy.
Assistant (Sisyphus (Ultraworker) · GLM-5 · 23.6s)
Fair point! Let me wrap up with a concise summary.
finalize.yml.tmpl Design Summary
Confirmed Decisions
| Area | Decision |
|---|---|
| Version | version: "0.0.1" |
| Plugin URI | git::repo@branch/commit, file://, more protocols later |
| Plugin runtime | Auto-detected by extension (.sh / .rhai) |
| Plugin config | Shallow override from publish: |
| Plugin communication | Shell: CLI args + ENV vars; Rhai: WIP |
| Plugin isolation | Via baker environment (Docker/VM = any plugin, bare-metal = PIP) |
| Fallible | Same semantics as bake.sh @fallible |
| Notification priority | Integers 0~INT_MAX, intra-group parallel, inter-group sequential fallback |
| Notification fallback | System-level: in-site DB → give up → admin |
| Empty group | Warn, don't auto-fix |
| Artifact ID | MD5(PUID + PATH), auto-generated if omitted |
| Artifact path | Glob → RE, 1 match = 1 artifact |
| Artifact transfer | Hard-link/rsync to plugin workspace |
| Duration format | ISO 8601 without P: "7D", "168H", or seconds |
| Typo fix | retension → retention |
| Token/Lock | System-managed, plugin coordination |
WIP / Deferred to Implementation
- Standalone plugin invocation
- Conditional system (
if:on artifacts/notifications) on_finish_ofcondition syntax- Variable system (
{{ build.* }},{{ target.* }}) - Retry/timeout per notification method
- Plugin token declaration (implicit vs explicit)
- Cleanup policies
- Schema validation
Ready to start implementation when you are. Good session!
Please read the conversation above and summarize.