Skip to content

Promote develop/1.0 to preview/1.0#246

Merged
petesramek merged 58 commits intopreview/1.0from
develop/1.0
Apr 21, 2026
Merged

Promote develop/1.0 to preview/1.0#246
petesramek merged 58 commits intopreview/1.0from
develop/1.0

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

No description provided.

petesramek and others added 30 commits April 4, 2026 10:23
…inks, add released versions table (#174)

Previously, versioned folders contained only API reference YAMLs while
guide pages were global (unversioned). The root `index.md` had entirely
broken links. The version switcher navigated to a bare `/{ver}/` folder
that has no `index.html`, causing 404s on GitHub Pages.

## Workflow (`publish-documentation.yml`)

- **Guide snapshot**: copies `api-reference/guide/` into
`api-reference/{ver}/guide/` immediately after API metadata generation,
so each version folder contains a full snapshot of both guide and API
reference
- **DocFX version groups**: each group now registers two content entries
— API YAMLs (`*.yml`) and guide pages (`guide/*.{md,yml}`) — producing
`_docs/{ver}/` and `_docs/{ver}/guide/` in the build output
- **Global TOC**: `Guide` nav link now points to
`{latest}/guide/introduction.html` instead of the unversioned `guide/`
- **index.md injection**: a single step builds the released versions
table and substitutes both `{version}` and `{versions_section}`
placeholders before `docfx build` runs (no committed artefacts)

## `api-reference/api-reference.json`

Removed `guide/*.{md,yml}` from the global content entry — guide pages
now exist only within versioned groups.

## `api-reference/index.md`

Replaced broken links with `{version}`-placeholder paths resolved at
build time. Added a `{versions_section}` placeholder that the workflow
expands into a full released-versions table, e.g.:

| Version | Guide | API Reference |
|---------|-------|---------------|
| v2.0 (latest) | [Guide](2.0/guide/introduction.html) | [API
Reference](2.0/PolylineAlgorithm.html) |
| v1.0 | [Guide](1.0/guide/introduction.html) | [API
Reference](1.0/PolylineAlgorithm.html) |

## `docs-versioning/public/version-switcher.js`

Fixed the fallback navigation branch (triggered when the user is not
inside a versioned path) to resolve the site root via the `docfx:rel`
meta tag and navigate to `/{ver}/PolylineAlgorithm.html` instead of the
bare `/{ver}/` folder.
…ced with plain nav links (#177)

The version picker was buried on the right side of the navbar next to
search and theme controls, and the Reference nav entry used a
per-version dropdown while Guide was a plain link — inconsistent and
counterintuitive.

## Changes

### Navbar layout (`_master.tmpl`)
- Removed `ms-auto` from `#version-picker-container` — it was already
before `#navbar` in DOM order, so dropping the margin pushes it left
- Added `flex-grow-1` to `#navbar` so search/theme controls remain
right-aligned

Result: `[Logo] [v1.1 ▾] [Guide] [API Reference] ——— [Search] [Theme]`

### CI toc.yml generation (`publish-documentation.yml`)
- Replaced the "Reference dropdown" step (loop over all versions →
`dropdown: true` + `items:`) with two plain links — `Guide` and `API
Reference` — both pointing to the latest version
- The version picker is now the single source of truth for version
selection

### Nav link version sync (`version-switcher.js`)
- Added `updateNavLinks(version)` — rewrites `href` on all same-origin
navbar `<a>` elements to reflect the active version
  - Uses `new URL(link.href)` for normalised absolute URL handling
  - Same-origin guard eliminates any `javascript:` scheme path
- Version input validated against `/^\d+(\.\d+)*$/` before any DOM
mutation
  - Extracted `VERSION_PATTERN` constant shared across the module
- Called on `window.load` (syncs links to the version in the current
URL) and on version-change before navigation

### Static toc.yml placeholder
- Added `API Reference` entry (pointing to `1.0/`) to reflect the
intended nav structure
…#181)

Version switcher on the global index page produced broken URLs like
`.../index.html/1.0/PolylineAlgorithm.html`, and even when corrected
would land users on the raw API reference — a poor first-visit
experience. Introduction was also redundant as a separate guide entry.

## Changes

### `version-switcher.js`
- **URL fix**: `getSiteRoot()` treated an empty `docfx:rel` meta
attribute as a valid relative URL, causing `new URL('',
'.../index.html')` to resolve to the full page path including the
filename. Now falls back to `'./'` when the attribute is empty.
- **Better redirect from index**: Selecting a version on the global
index now navigates to `{version}/guide/getting-started.html` instead of
`{version}/PolylineAlgorithm.html`.

```js
// Before
return meta ? meta.getAttribute('content') : './';
// After — empty string is falsy, so we fall back to './'
return meta ? (meta.getAttribute('content') || './') : './';
```

### `api-reference/guide/toc.yml`
- Removed the **Introduction** entry; **Getting Started** is now the
first and default page in the versioned guide sidebar.

### `api-reference/index.md`
- Replaced the bare link list with a proper landing page: library
summary, key benefits, and a quick-start install snippet — content drawn
from `introduction.md`. The `{versions_section}` placeholder is
preserved for workflow injection.

### `publish-documentation.yml`
- Navbar `toc.yml` generation and the versions table both updated to
link to `getting-started.html` instead of the now-removed
`introduction.html`.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
…itions (#184)

## Summary

Adds `.github/workflows/backtrack.yml` — an automated workflow that
back-merges changes from higher branches into lower branches after a PR
is merged, with branch locking to prevent race conditions.

## Background

Currently the back-merges (e.g. `Merge branch 'preview/1.0' into
develop/1.0`) are done manually. Without any coordination, a developer
could push a commit to `develop/M.n` between the moment the workflow
reads the branch tip and when it pushes the merge — causing the push to
fail or producing an incorrect merge base.

## What the workflow does

**Trigger**: any PR that is _merged_ into `preview/**` or `release/**`

| Source (base_ref) | Backtrack cascade |
|---|---|
| `preview/M.n` | `preview/M.n → develop/M.n` |
| `release/M.n` | `release/M.n → preview/M.n → develop/M.n` |

**Race-condition protection**:
1. `develop/M.n` is **locked** (branch protection applied) before any
merge begins — blocking concurrent direct pushes from developers.
2. All pushes use `GH_ADMIN_TOKEN`, which bypasses `enforce_admins:
false` protection — so the workflow can push even to a locked branch.
3. `develop/M.n` is **unlocked** in an `always()` step keyed on
`steps.lock-develop.outcome != 'skipped'` — ensures cleanup even if a
merge fails.
4. `preview/M.n` is already permanently locked by `promote-branch.yml`
and does not need extra lock/unlock steps; the admin token bypasses it
for the release→preview merge.

## Impact on other workflows

- **`bump-version.yml`**: unaffected — it creates brand-new branches via
`workflow_dispatch` (no PR merge event) and pushes to branches that have
no protection yet.
- **`promote-branch.yml`**: unaffected — it handles forward promotion
and creates/locks branches on first creation.
- **`release.yml`**: unaffected — it handles building, publishing, and
creating support branches.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
…ed (#186)

- [x] Understand the gap: base branch (`github.base_ref`) was not locked
during backtracking, allowing new PR merges into it concurrently
- [x] Lock base branch (`github.base_ref`) with `lock-branch: 'true'`
before the merge steps
- [x] Restore permanent protection on base branch after backtrack
(always, guarded by lock step outcome)
- [x] Initial parameterization of lock/unlock actions
- [x] Lock action: replaced `bypass-users` (user list) with
`bypass-admins` boolean — `true` sets `enforce_admins: false` so admins
are exempt from all rules; default is `false` (admins are also subject
to rules)
…re active (#191)

The backtrack workflow's automated `POST /repos/.../merges` calls were
blocked by branch protection: `enforce_admins: true` combined with
`required_pull_request_reviews` rejects the Merges API even for admin
tokens — there's no bypass.

## Changes

**`lock/action.yml`** — adds `skip-pull-request-reviews` input. When
`true`, sends `required_pull_request_reviews: null` in the PUT payload
instead of the review config object:

```yaml
"required_pull_request_reviews": (if $skip_reviews then null else {
  "dismiss_stale_reviews": $dismiss_stale,
  "require_code_owner_reviews": false,
  "required_approving_review_count": $review_count
} end)
```

**`backtrack.yml`** — the two "unlock for merge" steps (preview and
develop branches) now pass `skip-pull-request-reviews: 'true'`. The
existing `always()`-guarded restore steps re-apply full PR review
requirements after each merge regardless of outcome.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
…omated merges (#193)

The backtrack workflow locked concrete branches (e.g., `preview/1.0`,
`develop/1.0`) during automated merges but never properly cleaned them
up — the "restore" steps called the `lock` action with `lock-branch:
false`, which issues a `PUT` that modifies the rule but leaves the full
protection ruleset in place. Branches with no prior protection ended up
permanently protected after each run.

## Changes

- **`backtrack.yml`** — Replace all three "Restore protection" steps
with the `unlock` action (`DELETE /branches/{branch}/protection`)
instead of `lock` with `lock-branch: false` (`PUT
/branches/{branch}/protection`). Concrete per-branch rules are fully
removed after the merge; the manually-maintained glob pattern rules
(`develop/**`, `preview/**`, `release/**`) remain as the base
protection.

```yaml
# Before — PUT: flips lock_branch off but leaves the full ruleset behind
- uses: './.github/actions/github/branch-protection/lock'
  with:
    branch: ${{ steps.targets.outputs.develop-branch }}
    token: ${{ secrets.GH_ADMIN_TOKEN }}
    lock-branch: 'false'

# After — DELETE: removes the temporary concrete rule entirely
- uses: './.github/actions/github/branch-protection/unlock'
  with:
    branch: ${{ steps.targets.outputs.develop-branch }}
    token: ${{ secrets.GH_ADMIN_TOKEN }}
    fail-on-error: 'true'
```
…ired_linear_history in branch protection payload (#196)

The backtrack workflow was failing with HTTP 409 ("This branch must not
contain merge commits") because the `preview/*` branches have
`required_linear_history: true` in their protection. The lock action's
payload omitted the field entirely, so GitHub preserved the existing
`true` value even during the "unlock for merge" phase.

## Changes

- **`lock/action.yml`** — Added `required-linear-history` input
(default: `false`) and included `"required_linear_history":
$required_linear_history` in the branch protection PUT payload. Because
the default is `false`, the existing "unlock for merge" calls in
`backtrack.yml` now explicitly send `false` without requiring any
call-site changes, overriding the previously preserved `true` value
before the merge API is invoked.

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
…omposite action (#203)

- [x] Add `develop/**` to `branches` filter in
`.github/workflows/pull-request.yml`
Copilot AI and others added 27 commits April 4, 2026 18:13
… to always attempt branch creation (#205)

The `workflow-variables` job in `promote-branch.yml` had no
`actions/checkout` step, so `origin` was never configured as a git
remote. `git ls-remote --exit-code --heads origin <target-branch>`
always failed (exit non-zero), and with `set +e` the error was swallowed
— resulting in `target-branch-exists` always being `false`. The
`promote-branch` job then unconditionally tried to create the target
branch from `origin/main`, which was rejected as a non-fast-forward push
when the branch already existed ahead of `main`.

## Changes

- **`.github/workflows/promote-branch.yml`**: Add `actions/checkout@v6`
as the first step in `workflow-variables` so `origin` is configured
before `git ls-remote` runs, enabling the `target-branch-exists` guard
to work correctly.
…ch workflow (#206)

`gh pr create --fill` computes the PR body by running `git log
origin/<target>...HEAD`, but the shallow checkout (`fetch-depth: 1`)
only fetches the source branch. With `origin/<target>` absent from the
local repo, git fails with "ambiguous argument" and the job exits
non-zero.

## Changes

- **`.github/workflows/promote-branch.yml`** — add `git fetch origin ${{
env.target-branch }}` immediately before `gh pr create` in the "Create
PR" step, ensuring the remote tracking ref exists when `--fill` computes
the commit range.
`gh release create` requires the tag to exist on the remote — creating
it locally with `git tag` is not sufficient. The job was failing every
time with:

```
tag 1.0.69.11 exists locally but has not been pushed to petesramek/polyline-algorithm-csharp,
please push it before continuing or specify the `--target` flag to create a new tag
```

## Change

- **`.github/actions/github/create-release/action.yml`** — push the
annotated tag to `origin` immediately after creating it, before invoking
`gh release create`

```diff
     run: |
       git tag -a ${{ inputs.release-version }} -m "${{ inputs.release-version }}"
+      git push origin ${{ inputs.release-version }}
```
The `merge-to-main` job was failing because `GITHUB_TOKEN` lacked
`pull-requests: write`, causing `gh pr create` to be rejected with
`GraphQL: Resource not accessible by integration (createPullRequest)`.

## Change

- Added job-level `permissions` block to `merge-to-main` with
`pull-requests: write` and `contents: read`, scoped only to the job that
needs it rather than elevating the entire workflow.

```yaml
merge-to-main:
  ...
  permissions:
    pull-requests: write
    contents: read
```
)

Support branches created during release are explicitly locked via the
`branch-protection/lock` action, but this is unnecessary — the repo
already has a `support/**` glob pattern branch protection rule that
applies automatically to any newly pushed branch matching that pattern.

## Changes

- **`release.yml`**: Removed the `Lock support branch` step from the
`create-support-branch` job
- **`release.yml`**: Updated the step summary message from "Created and
locked" to "Created"

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
…CI (#219)

- [x] Fix RS0017 enforcement via `<WarningsAsErrors>` in csproj
- [x] Restore `#nullable enable` to `PublicAPI.Shipped.txt` —
accidentally emptied by the RS0017 test cleanup (`head -n -2` overshot
on a 1-line file)
- [x] All 222 tests pass; build clean (0 errors)
- [x] Understand existing NTS sample pattern and abstract
encoder/decoder structure
- [x] Create `samples/PolylineAlgorithm.SensorData.Sample/` project with
`SensorDataEncoder`, `SensorDataDecoder`, `SensorReading`, `Program.cs`
- [x] Make both sample projects console apps (`OutputType=Exe`,
`net10.0`)
- [x] Register sensor data project in `PolylineAlgorithm.slnx`
- [x] Inline `DecodeIterator` body directly into `Decode`, remove the
separate method (suppress S4456)
- [x] Encode/decode `Timestamp` as Unix epoch seconds (precision 0) —
each reading encodes a [timestamp_delta, temperature_delta] pair
- Base epoch 2020-01-01 UTC (1,577,836,800 s) used to keep first delta
within int32 safe range of the polyline algorithm
- `SensorDataEncoder.TimestampBaseEpochSeconds` constant shared by both
encoder and decoder
- [x] Update `Program.cs` to display recovered timestamps in decoded
output
- [x] Build verified — 0 errors, 0 warnings
This pull request makes a small update to the `Normalize` method in
`PolylineEncoding.cs` to improve floating-point rounding accuracy. The
change introduces a tiny epsilon adjustment to ensure more reliable
normalization of values, especially for edge cases near rounding
boundaries.

- Improved floating-point normalization in the `Normalize` method by
adding a small epsilon (`1e-9`) multiplied by the sign of the value,
which helps avoid rounding errors when converting doubles to integers.
(`src/PolylineAlgorithm/PolylineEncoding.cs`,
[src/PolylineAlgorithm/PolylineEncoding.csR79-L82](diffhunk://#diff-94e762d41cb6a61885715f59c854d8a5f386d0829c01ff285ff2073fb1bc6654R79-L82))
This pull request improves the project's GitHub workflows and
documentation templates to streamline issue reporting, feature requests,
pull requests, and dependency management. It introduces clearer
templates for bug reports and feature requests, adds a security policy,
and enhances automation settings for dependency updates.

**Issue and PR Template Improvements:**

* Updated `.github/ISSUE_TEMPLATE/bug_report.md` to require a minimal
code snippet for reproducing bugs, clarified expected vs. actual
behavior, and standardized environment information.
[[1]](diffhunk://#diff-185833cb26d7ac66a4d39042fd576a820c2c2c6d05ad18973bb9c7dce77267c5L4-R5)
[[2]](diffhunk://#diff-185833cb26d7ac66a4d39042fd576a820c2c2c6d05ad18973bb9c7dce77267c5L14-R29)
* Updated `.github/ISSUE_TEMPLATE/feature_request.md` to pre-fill the
title and label for feature requests, ensuring consistency.
* Added a new pull request template (`.github/PULL_REQUEST_TEMPLATE.md`)
to guide contributors on summaries, change types, and checklists for PR
quality.

**Security and Community Guidelines:**

* Added a `SECURITY.md` file outlining the supported versions, how to
report vulnerabilities, and response expectations.
* Updated `.github/ISSUE_TEMPLATE/config.yml` to disable blank issues
and direct general questions to GitHub Discussions.

**Automation and Dependency Management:**

* Enhanced `.github/dependabot.yml` to automatically label dependency
PRs with "dependencies" and assign them to "petesramek" for all package
ecosystems.
…orkflow fixes (#223)

## Summary

Repository health improvements across 8 areas.

## Changes

### New files
- **`.github/CODEOWNERS`** – assigns `@petesramek` as owner of
`.github/`, `src/`, and `tests/`
- **`CODE_OF_CONDUCT.md`** – Contributor Covenant 2.1 with "project
maintainer" as enforcement contact
- **`CHANGELOG.md`** – minimal changelog that links to the [GitHub
Releases
page](https://github.com/petesramek/polyline-algorithm-csharp/releases)

### Workflow fixes (`.github/workflows/pull-request.yml`)
- **Fix trailing-quote bug** – removed stray `'` from the
`dotnet-sdk-version` parameter in the `publish-development-package` job
- **Fix benchmark `if` condition** – replaced invalid
`github.env.is_release` context with
`needs.workflow-variables.outputs.is-release == 'true'`; added
`workflow-variables` to the benchmark job's `needs` so the output is
available
- **Add `security` job** – new job that runs `dotnet list
src/PolylineAlgorithm/PolylineAlgorithm.csproj package --vulnerable
--include-transitive` after build; fails on non-zero exit

### Source Link (`Directory.Build.props`)
- Added `<EmbedUntrackedSources>true</EmbedUntrackedSources>` and
`<DebugType>embedded</DebugType>` to the first `PropertyGroup`
- Added `Microsoft.SourceLink.GitHub` version `8.*` (no known
vulnerabilities per GitHub Advisory Database) to the analyzer
`ItemGroup`

### Documentation (`docs/local-development.md`)
- Added **"Required Repository Secrets and Variables"** section listing:
  - Secret: `NUGET_PACKAGE_FEED_API_KEY`
- Variables: `NUGET_PACKAGE_FEED_URL`, `BENCHMARKDOTNET_RUN_OVERRIDE`,
`BENCHMARKDOTNET_RUNTIMES`, `BENCHMARKDOTNET_FILTER`,
`DEFAULT_BUILD_FRAMEWORK`, `SRC_DEFAULT_GLOB_PATTERN`

## Verification
- `dotnet build PolylineAlgorithm.slnx --configuration Release` passes
with 0 errors
- CodeQL security scan: 0 alerts

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: petesramek <2333452+petesramek@users.noreply.github.com>
`CHANGELOG.md` had no automated update mechanism — entries had to be
added manually or not at all. This wires the existing `gh release create
--generate-notes` output directly into `CHANGELOG.md` on every stable
release.

## What changed

### `.github/release.yml` (new)
Configures GitHub's auto-generated release note categories via PR
labels: `breaking`, `feat`/`enhancement`, `fix`/`bug`,
`docs`/`documentation`. Unlabelled PRs fall into "Other Changes";
`ignore-for-release` suppresses an entry entirely.

### `CHANGELOG.md`
Replaced the placeholder with a Keep a Changelog header and an HTML
comment marker that the workflow targets for insertion:
```
<!-- New entries are prepended automatically by the release workflow. -->
```

### `.github/workflows/release.yml` — `update-changelog` job
New job, runs after `release`, stable branches only (`is-release ==
'true'`):
1. Fetches the release body: `gh release view <version> --json body --jq
'.body'`
2. Inserts `## <version> — YYYY-MM-DD` + release notes immediately after
the comment marker using `awk`, leaving the rest of the file intact
3. Commits and pushes back to `release/X.Y` (same pattern as the
existing `promote-api-files` job)

`merge-to-main` gains `update-changelog` in its `needs`, so the PR to
`main` always includes the updated file.

### `.github/PULL_REQUEST_TEMPLATE.md`
Added checklist item: apply one of the release-note label categories
(`breaking` / `feat` / `fix` / `docs`).

### `docs/workflows.md`
Added `update-changelog` row to the `release.yml` job table.
The API reference landing page versions table had no link to per-version
changelog/release notes.

## Changes

- **`publish-documentation.yml`**: Added a "Release Notes" column to the
generated "Released Versions" table; each entry links to the
corresponding GitHub Release page (`releases/tag/v<version>`), which is
already auto-populated from `CHANGELOG.md` by the release workflow.

The generated table now looks like:

| Version | Guide | API Reference | Release Notes |
|---------|-------|---------------|---------------|
| v1.0 (latest) | Guide | API Reference | [Release
Notes](https://github.com/petesramek/polyline-algorithm-csharp/releases/tag/v1.0)
|
- [x] Remove `benchmark` job from `pull-request.yml`
- [x] Add `benchmark` job to `release.yml` (same definition, needs
`[workflow-variables, build, validate-release]`)
- [x] Update `publish-documentation` job in `release.yml` to depend on
`benchmark`
- [x] In `publish-documentation.yml`: replace inline `dotnet run`
execution with `download-artifact` (pattern `benchmark-*`,
`merge-multiple: true`) + awk injection into `benchmarks.md`
@petesramek petesramek enabled auto-merge (squash) April 21, 2026 13:51
@github-actions github-actions Bot deployed to Development April 21, 2026 13:54 Active
@petesramek petesramek merged commit e1b7fa7 into preview/1.0 Apr 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants