Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/rulesets/main-protection.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
}
],
"bypass_actors": [
{"actor_id": 5, "actor_type": "RepositoryRole", "bypass_mode": "always"}
{"actor_id": 15368, "actor_type": "Integration", "bypass_mode": "pull_request"}
]
}
33 changes: 28 additions & 5 deletions .github/workflows/news-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ on:

permissions:
contents: write
pull-requests: write

concurrency:
group: news-sync
cancel-in-progress: false

jobs:
sync-news:
Expand All @@ -29,11 +34,29 @@ jobs:
YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY }}
run: ./sap-devs news fetch-index --output content/packs/base/news-episodes.json

- name: Commit if changed
- name: Open or update PR if changed
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git diff --quiet content/packs/base/news-episodes.json 2>/dev/null || \
(git add content/packs/base/news-episodes.json && \
git commit -m "chore: update news episode index" && \
git push)
if git diff --quiet content/packs/base/news-episodes.json 2>/dev/null; then
echo "No changes."
exit 0
fi
BRANCH="bot/news-sync-update"
git checkout -B "$BRANCH"
git add content/packs/base/news-episodes.json
git commit -m "chore: update news episode index"
git push -f origin "$BRANCH"
EXISTING=$(gh pr list --head "$BRANCH" --json number -q '.[0].number // empty' 2>/dev/null || echo "")
if [ -z "$EXISTING" ]; then
gh pr create \
--title "chore: update news episode index" \
--body "Automated update of \`content/packs/base/news-episodes.json\`." \
--base main --head "$BRANCH"
else
echo "PR #$EXISTING already open; new commit pushed to $BRANCH"
fi
gh pr merge --auto --squash "$BRANCH" || \
echo "::warning::auto-merge not armed; check 'Allow auto-merge' is enabled in repo Settings"
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ gh release edit vX.Y.Z --draft=false --latest --notes "release notes here"
3. `sign-windows.yml` (workflow_run on Tray success, env: `signing`) → **pauses for required-reviewer approval** (OSPO gate), then Authenticode-signs Windows `.exe` binaries via SignPath.io and publishes the release (best-effort)
4. Manual: `gh release edit --draft=false` only needed if signing is skipped — otherwise the signing job publishes automatically after approval

**OSPO compliance:** `main` is protected by ruleset (`main-protection`: requires PR + CI `test` check, blocks force-push and deletion, admins can bypass). Workflows that touch secrets or publish artifacts run in named environments: `release`, `signing` (required reviewer = repo admin), `news-sync`. SignPath secrets and `YOUTUBE_API_KEY` should be scoped to their respective environments rather than the org/repo level. Ruleset spec: [.github/rulesets/main-protection.json](.github/rulesets/main-protection.json).
**OSPO compliance:** `main` is protected by ruleset (`main-protection`: requires PR + CI `test` check, blocks force-push and deletion). Admins **cannot** bypass — every change to `main` goes through a PR with one approving review and a passing `test` check. The `github-actions[bot]` integration has a narrow `pull_request`-mode bypass so automated PRs (notably `news-sync`) can self-merge once their `test` check passes; it cannot push directly to `main`. Workflows that touch secrets or publish artifacts run in named environments: `release`, `signing` (required reviewer = repo admin), `news-sync`. SignPath secrets and `YOUTUBE_API_KEY` should be scoped to their respective environments rather than the org/repo level. Ruleset spec: [.github/rulesets/main-protection.json](.github/rulesets/main-protection.json).

**Artifacts per release:** CLI binaries (linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64) + tray binaries (linux/amd64, darwin/arm64, windows/amd64) + checksums + tray-checksums + Scoop manifest + Homebrew cask.

Expand Down
69 changes: 69 additions & 0 deletions docs/ospo-admin-demotion-draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# OSPO Control 7 — Admin Demotion Draft

**Status:** Draft — pending project owner action. **Nothing is executed by the OSPO hardening PR.**

OSPO Hardening Control 7 ("Access Restrictions") flagged 25 admins on this repository, well above the least-privilege threshold of 3–5. This document classifies the roster and proposes per-account actions.

## Bucket 1 — Project leads (keep admin)

| Login | Rationale |
|---|---|
| `qmacro` | Project lead |
| `jung-thomas` | Project owner |
| `ajmaradiaga` | Active maintainer (Developer Advocacy) |

## Bucket 2 — Org-mandated (cannot demote at repo level)

These admins are inherited from SAP organization-level membership or are platform automation. Removing them from the repo collaborator list does not actually remove their admin powers; that requires an OSPO ticket or org-admin action.

- `SAP-OSPO-ADMIN`
- `sap-ospo-bot`
- `SebastianWolf-SAP`
- `nicoschoenteich`
- `christianneu`
- `dellagustin-sap`

**Action:** verify with OSPO. If the inherited grant is intentional, leave alone. If a subset can be pruned via OSPO ticket, file one.

## Bucket 3 — Inherited / unclear (propose demote to `maintain` or `write`)

These accounts have admin but no obvious active stake in this repo. Recommended action: demote each to `maintain` (still allows triaging issues, accepting PRs, managing labels) or `write` (just code contribution). Confirm per-account before demoting; demotion notifies the user.

| Login | Suggested role after demotion |
|---|---|
| `akula86` | maintain |
| `ihrigb` | maintain |
| `vipinvkmenon` | maintain |
| `Sygyzmundovych` | maintain |
| `KevinRiedelsheimer` | maintain |
| `rbrainey` | maintain |
| `thecodester` | maintain |
| `ajinkyapatil8190` | maintain |
| `Shegox` | maintain |
| `rich-heilman` | maintain |
| `noravth` | maintain |
| `sheenamk` | maintain |
| `PoojaGidaveer` | maintain |
| `btbernard` | maintain |
| `ajaysoreng` | maintain |
| `neelamegams` | maintain |

## Demotion command (per account)

```bash
gh api -X PUT repos/SAP-samples/sap-devs-cli/collaborators/<login> \
-f permission=maintain
```

Expected response: `204 No Content`. The user receives an email notification.

## Expected end state

| Bucket | Count |
|---|---|
| Admin (project leads) | 3 |
| Admin (org-mandated, awaiting OSPO) | 6 |
| Demoted to `maintain` | 16 |
| **Net admin count** | **9** (or fewer once OSPO bucket is pruned) |

This brings the repo close to OSPO Control 7's least-privilege threshold (3–5) without disrupting active maintainers.
Loading
Loading