Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Adopt ProjectTemplate Docker release pipeline and conventions by ptr727 · Pull Request #61 · ptr727/ESPHome-NonRoot · GitHub
Skip to content

Adopt ProjectTemplate Docker release pipeline and conventions - #61

Merged
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern
Jun 21, 2026
Merged

Adopt ProjectTemplate Docker release pipeline and conventions#61
ptr727 merged 8 commits into
developfrom
adopt-projecttemplate-docker-pattern

Conversation

@ptr727

Copy link
Copy Markdown
Owner

Brings ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a Docker-only derived repo, and keeps it consistent with the sibling downstreams homeassistant-purpleair and NxWitness.

Pipeline (template two-layer model)

  • Orchestration carried verbatim:get-version-task.yml, build-datebadge-task.yml, publish-release.yml, and the get-version + github-release jobs in build-release-task.yml.
  • Build layer (owned):build-docker-task.yml. Dropped the nuget/pypi/executable targets, the publish-pypi job, and the .NET unit-test job from test-pull-request.yml (the ruleset-bound Check pull request workflow status aggregator is preserved).
  • Two-phase release (PUBLISH_ON_MERGE unset): PRs smoke-test linux/amd64 only; the weekly schedule + manual dispatch publish both branches.

ESPHome-specific behavior (preserved, sibling-aligned)

  • Image tags:latest/:develop + the pinned upstream ESPHome version, also passed as the ESPHOME_VERSION build-arg, read from the committed .github/esphome-version.json.
  • check-esphome-version.yml replaces CheckUpstreamRelease.yml, mirroring purpleair's check-ha-version.yml: resolves the latest ESPHome from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted over main + develop, since the version is shipped content) that merge-bot auto-merges; the next publish ships it.
  • publish-docker-readme-task.yml mirrors NxWitness: pushes a static Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions machinery and the DOCKER_HUB_PASSWORD secret.

Verbatim carries / config

AGENTS.md (Docker-only adaptation), .github/copilot-instructions.md, .markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted inline), .gitattributes. Added a dual-target docker Dependabot ecosystem; pointed the README build badge at publish-release.yml.

Local verification

  • actionlint (with shellcheck) and markdownlint-cli2 both clean.
  • docker buildx build --platform linux/amd64 --build-arg ESPHOME_VERSION=2026.6.2 succeeds; esphome version in the image reports 2026.6.2, matching the state file.

Two-phase latency note

In the two-phase model, a merged ESPHome-version bump ships on the next weekly/dispatch publish rather than within ~24h (matching NxWitness). Flip PUBLISH_ON_MERGE=true or add a post-merge dispatch if prompt rebuilds are wanted.

Follow-up (maintainer / GitHub-side)

  • Import the develop/main rulesets; set PUBLISH_ON_MERGE unset; enable "Allow GitHub Actions to create and approve pull requests".
  • Secrets: DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (no more DOCKER_HUB_PASSWORD); create/install the ptr727-codegen GitHub App and add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to the Actions and Dependabot secret stores (powers merge-bot and the version tracker).
  • Upstream template-gap issues will be filed at ptr727/ProjectTemplate (no upstream-rebuild pattern, external-version docker tag, unit-test .NET coupling, .editorconfig C# block, no Docker Hub README task).

🤖 Generated with Claude Code

Bring ESPHome-NonRoot in-line with ptr727/ProjectTemplate (develop) as a
Docker-only derived repo: carry the cross-cutting contract verbatim and
re-sync it going forward, while preserving the three ESPHome-specific
behaviors the template has no equivalent for.
Pipeline: replace the monolithic BuildDockerPush.yml with the template's
two-layer model. Orchestration is carried verbatim (get-version-task,
build-datebadge-task, publish-release, and the get-version + github-release
jobs in build-release-task); the build layer is the owned build-docker-task
leaf. Drop the nuget/pypi/executable targets and the publish-pypi job, and
the .NET unit-test job from test-pull-request, keeping the ruleset-bound
"Check pull request workflow status" aggregator. Two-phase model
(PUBLISH_ON_MERGE unset): PRs smoke-test amd64 only; the weekly schedule and
manual dispatch publish both branches.
ESPHome-specific behavior, aligned with sibling downstreams:
- build-docker-task tags :latest/:develop plus the pinned upstream ESPHome
version and passes it as the ESPHOME_VERSION build-arg, read from the
committed .github/esphome-version.json state file.
- check-esphome-version replaces CheckUpstreamRelease, mirroring
homeassistant-purpleair's check-ha-version: it resolves the latest ESPHome
from PyPI and opens a rolling, App-authored, signed bump PR (dual-targeted
across main and develop since the version is shipped content) that
merge-bot auto-merges and the next publish ships.
- publish-docker-readme-task mirrors NxWitness: it pushes a static
Docker/README.md via DOCKER_HUB_ACCESS_TOKEN, replacing the m4/toolversions
machinery and the DOCKER_HUB_PASSWORD secret.
Carry verbatim: AGENTS.md (Docker-only adaptation), copilot-instructions.md,
.markdownlint-cli2.jsonc, .editorconfig (C# block trimmed, deviation noted),
.gitattributes. Add a dual-target docker Dependabot ecosystem and point the
README build badge at publish-release.yml.
CopilotAI review requested due to automatic review settings June 20, 2026 20:31
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Maintainer GitHub-side setup runbook

I automated what was safe; the rest needs you. Summary of what I checked:

  • Repo already has develop + main rulesets (correctly named) and no classic branch protection - good. But the existing rulesets are minimal (deletion only); they do not enforce signed commits, the required status check, or the per-branch merge methods.
  • Allow GitHub Actions to create and approve pull requests is already enabled (can_approve_pull_request_reviews: true); default_workflow_permissions: read is fine (workflows declare explicit per-job permissions:).
  • PUBLISH_ON_MERGE is unset = two-phase (intended). Leave it unset.

1. Rulesets - NOT auto-imported (brownfield, maintainer-only)

origin/main and origin/develop each contain 51 unsigned commits in history. The template's rulesets enable Require signed commits, which - per AGENTS.md "Branching Model" and the brownfield migration procedure - can block the first develop -> main release on a repo with unsigned history and requires a force-push re-sign that an AI agent must never perform. So I left the rulesets untouched.

To bring them up to the template (your call):

# Export the template's two rulesets (writable fields only)fornamein develop main;do
id=$(gh api repos/ptr727/ProjectTemplate/rulesets --jq ".[] | select(.name==\"$name\") | .id")
gh api "repos/ptr727/ProjectTemplate/rulesets/$id" \
--jq '{name, target, enforcement, bypass_actors, conditions, rules}'>"$name-ruleset.json"done# Either delete the two minimal same-named rulesets and re-create,# or full-payload PUT them (rename not needed - names already match).# Existing ids: develop=918710 main=918708# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918710# gh api -X DELETE repos/ptr727/ESPHome-NonRoot/rulesets/918708fornamein develop main;do
gh api -X POST repos/ptr727/ESPHome-NonRoot/rulesets --input "$name-ruleset.json"done

Because of the unsigned history, before/after enabling Require signed commits follow the brownfield procedure (re-sign divergent history, temporarily set the ruleset Enforcement to Disabled for the one-time force-push, re-enable). The required status-check context resolves to Check pull request workflow status and only turns green after test-pull-request.yml runs once.

2. Secrets

  • DOCKER_HUB_USERNAME, DOCKER_HUB_ACCESS_TOKEN (Actions store; Dependabot store too if needed). The token needs write scope - the Docker buildcache cache-to pushes to the registry (the old type=gha cache did not). DOCKER_HUB_PASSWORD is no longer needed (the README push now uses the access token).
  • GitHub App for the bots: create + install ptr727-codegen, then add CODEGEN_APP_CLIENT_ID + CODEGEN_APP_PRIVATE_KEY to both the Actions and Dependabot secret stores. This App powers both merge-bot-pull-request.yml (Dependabot auto-merge) andcheck-esphome-version.yml (the rolling version-bump PR).

3. Verify after merge

workflow_dispatchpublish-release.yml once and confirm: multi-arch image + :develop/:latest + :<esphome-version> tags pushed, a GitHub release at the NBGV SemVer2 tag, date badge updated, the docker-readme job pushing Docker/README.md, and no PyPI/NuGet steps. Then workflow_dispatchcheck-esphome-version.yml to confirm it opens a signed bump PR only when PyPI is ahead of .github/esphome-version.json.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns ESPHome-NonRoot with the ptr727/ProjectTemplate “Docker-only derived repo” conventions by replacing the legacy single-workflow build/push model with a two-layer reusable-workflow release pipeline, and by adopting the sibling-style upstream ESPHome version tracker + Docker Hub README publishing.

Changes:

  • Replaced the legacy BuildDockerPush.yml / CheckUpstreamRelease.yml workflows with a reusable-workflow orchestration model (publish-release.yml, test-pull-request.yml, and shared *-task.yml building blocks).
  • Added an ESPHome upstream version tracker (check-esphome-version.yml) that bumps .github/esphome-version.json via an App-authored PR flow.
  • Switched Docker Hub README publishing to a static Docker/README.md pushed via publish-docker-readme-task.yml, and updated repo linting/line-ending governance files (.editorconfig, .markdownlint-cli2.jsonc, .gitattributes).

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
README.mdUpdates pipeline references and workflow badge to the new release workflow.
Docker/README.mdAdds a static Docker Hub README source file.
Docker/README.m4Removes m4-based README generation source.
AGENTS.mdAdds template-derived repo conventions and workflow contracts.
.markdownlint-cli2.jsoncAdds markdownlint-cli2 configuration aligned to the template.
.github/workflows/test-pull-request.ymlAdds PR smoke-test workflow using reusable tasks and an aggregator check.
.github/workflows/publish-release.ymlAdds orchestrator workflow for scheduled/dispatch publishing and optional publish-on-merge.
.github/workflows/publish-docker-readme-task.ymlAdds reusable task to publish Docker Hub README from Docker/README.md.
.github/workflows/merge-bot-pull-request.ymlAdds/updates merge-bot workflow for Dependabot and ESPHome bump PRs.
.github/workflows/get-version-task.ymlAdds reusable NBGV versioning task for consistent tagging.
.github/workflows/check-esphome-version.ymlAdds daily upstream tracker that opens rolling bump PRs for both branches.
.github/workflows/build-release-task.ymlAdds reusable “build release” task that composes versioning + Docker build + GitHub release.
.github/workflows/build-docker-task.ymlAdds the Docker build/push task (repo-owned build layer).
.github/workflows/build-datebadge-task.ymlAdds reusable task for updating the BYOB date badge.
.github/esphome-version.jsonAdds committed ESPHome version state used for image tags and build args.
.github/dependabot.ymlAdds dual-target Dependabot updates and docker ecosystem entries.
.github/copilot-instructions.mdAdds Copilot runbook and repo-specific review mechanics pointering to AGENTS.md.
.gitattributesNormalizes/updates EOL governance header while keeping * -text.
.editorconfigAdds per-extension EOL and formatting rules aligned with the template.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadDocker/README.md Outdated
Comment thread.github/workflows/publish-release.yml Outdated
Comment thread.github/workflows/check-esphome-version.yml
Comment thread.github/workflows/build-docker-task.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Filed the template-gap issues upstream: ptr727/ProjectTemplate#157 (upstream-version tracker pattern), ptr727/ProjectTemplate#158 (docker tag from external version), ptr727/ProjectTemplate#159 (unit-test .NET coupling in test-pull-request), ptr727/ProjectTemplate#160 (.editorconfig C# block in a verbatim carry), ptr727/ProjectTemplate#161 (Docker Hub README task).

The pinned upstream version is a build-input version source, not GitHub
platform config, so it belongs beside version.json at the repo root rather
than under .github/. Update build-docker-task, check-esphome-version,
test-pull-request, and AGENTS.md references.
@ptr727ptr727 closed this Jun 20, 2026
@ptr727ptr727 reopened this Jun 20, 2026
Forces a fresh pull_request merge-ref so reusable workflows resolve from the
current head (the prior run executed a stale merge-ref after a close/reopen).
No content change; squashed away on merge to develop.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/check-esphome-version.yml Outdated
Comment threadDocker/README.md Outdated
…and doc cadence
- build-docker-task: self-gate push and cache-to on !smoke (defense-in-depth)
- check-esphome-version: ref-independent concurrency group so the scheduled
run and a manual dispatch can't race the esphome-version-bump/* branches
- Docker/README.md: describe the two-phase publish cadence accurately
- publish-release.yml: base-image example matches python:3.13-slim
jq emits LF; .editorconfig requires CRLF for *.json and .gitattributes
disables EOL normalization, so convert the rewritten file to CRLF before
committing or every bump PR would flip it to LF.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated no new comments.

…ules
- Drop sibling-repo references (other repos are not relevant to a reviewer)
- Drop AGENTS.md/ruleset rule-citations from authored comments; state the
intrinsic reason instead
- Correct the Docker Hub login comment: this is a public repo, so describe the
authenticated-pull logic and its real fork-PR consequence rather than a false
private-repo justification
- Login only when publishing so fork PR smoke builds (no secret access) can run
- Rephrase the no-op-republish comment to describe the skip behavior without
comparing to NuGet/PyPI registries this repo does not ship

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/test-pull-request.yml Outdated
Comment thread.github/workflows/build-docker-task.yml
Make comments short and reviewer-focused: describe what the code does, drop
historic/design background, cross-project references, and rule citations.
Remove the dead semver-major NuGet auto-merge guard and its metadata step (no
NuGet ecosystem here; behavior unchanged).
@ptr727
ptr727 requested a review from CopilotJune 21, 2026 01:10
@ptr727

Copy link
Copy Markdown
OwnerAuthor

Trimmed all workflow comments to concise current-state context (no cross-project refs, historic/design background, or rule citations; non-obvious-only). Net ~240 fewer comment lines; removed the dead semver-major NuGet auto-merge guard (no NuGet ecosystem here). Filed the comment-style observation upstream as ptr727/ProjectTemplate#162.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 2 comments.

Comment thread.github/workflows/build-release-task.yml
Comment thread.github/workflows/build-release-task.yml
@ptr727
ptr727 merged commit 48bdaa7 into developJun 21, 2026
11 checks passed
@ptr727
ptr727 deleted the adopt-projecttemplate-docker-pattern branch June 21, 2026 01:33
Sign up for freeto 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

@ptr727