Promote develop/1.0 to preview/1.0#240
Merged
petesramek merged 52 commits intopreview/1.0from Apr 21, 2026
Merged
Conversation
…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`
- [x] Restore `Validate pull request` step in `validate-promotion` job - [x] Keep `Lock target branch` step removed from `promote-branch` job
… 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`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Removed SIMD validation in favor of one pass loop.