chore: import upstream snapshot with attribution
Check engine pin consistency / Dockerfile / CI pin consistency (push) Successful in 8s
Sirius CI/CD Pipeline / Detect Changes (push) Successful in 23s
Validate Docker Configuration / Validate Docker Compose Configuration (push) Successful in 47s
Sirius CI/CD Pipeline / Build API (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build UI (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Engine Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge API Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Merge UI Manifest (push) Has been cancelled
Sirius CI/CD Pipeline / Build Engine (${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Build Infra (${{ matrix.service }}, ${{ matrix.platform }}) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-postgres) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-rabbitmq) (push) Has been cancelled
Sirius CI/CD Pipeline / Merge Infra Manifest (sirius-valkey) (push) Has been cancelled
Sirius CI/CD Pipeline / Integration Test (push) Has been cancelled
Sirius CI/CD Pipeline / Public Stack Contract (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Deployment (sirius-demo branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Dispatch Demo Canary (main branch) (push) Has been cancelled
Sirius CI/CD Pipeline / Guard Registry Namespace (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:32:25 +08:00
commit 161ef94b4f
708 changed files with 189571 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
name: Auth or 401 Issue
description: Report API key drift, auth mismatches, and unauthorized responses.
title: "[auth/401]: "
labels:
- status:needs-triage
- type:bug
- area:auth
body:
- type: markdown
attributes:
value: |
Use this form for `401` responses, API key mismatch, and auth surface incidents.
This maps directly to the API key operations runbook.
- type: input
id: endpoint
attributes:
label: Endpoint/Surface Affected
placeholder: "e.g. /host/, tRPC scanner.getScanStatus, /api/v1/keys"
validations:
required: true
- type: dropdown
id: symptom
attributes:
label: Primary Symptom
options:
- 401 on non-health API routes
- UI cannot read/write through tRPC
- scanner/agent submissions return 401
- key rotation appears incomplete
- unknown auth failure
validations:
required: true
- type: checkboxes
id: runbook_checks
attributes:
label: Runbook Checks Completed
options:
- label: I verified `SIRIUS_API_KEY` is set and non-empty in all runtime services.
required: true
- label: I confirmed services are using the same active key (`sirius-api`, `sirius-ui`, `sirius-engine`).
required: true
- label: I re-ran installer and restarted services after any key changes.
required: false
- type: textarea
id: evidence
attributes:
label: Diagnostics and Evidence
description: Include key env checks and relevant logs.
placeholder: |
docker inspect sirius-api --format '{{range .Config.Env}}{{println .}}{{end}}' | rg '^SIRIUS_API_KEY='
docker inspect sirius-ui --format '{{range .Config.Env}}{{println .}}{{end}}' | rg '^SIRIUS_API_KEY='
docker inspect sirius-engine --format '{{range .Config.Env}}{{println .}}{{end}}' | rg '^SIRIUS_API_KEY='
docker compose logs --no-color --tail=120 sirius-api sirius-ui sirius-engine
validations:
required: true
- type: textarea
id: repro_steps
attributes:
label: Reproduction Steps
placeholder: "Provide exact, minimal steps to reproduce."
validations:
required: true
+60
View File
@@ -0,0 +1,60 @@
name: Bug Report
description: Report a reproducible defect in Sirius Scan.
title: "[bug]: "
labels:
- status:needs-triage
- type:bug
body:
- type: markdown
attributes:
value: |
Thank you for reporting a bug. Please provide enough detail for maintainers to reproduce quickly.
- type: input
id: component
attributes:
label: Affected Component
placeholder: "e.g. sirius-api, sirius-ui, scanner workflow, docker startup"
validations:
required: true
- type: input
id: version
attributes:
label: Version
placeholder: "e.g. v1.0.0, main, commit SHA"
validations:
required: true
- type: textarea
id: steps
attributes:
label: Reproduction Steps
placeholder: |
1. ...
2. ...
3. ...
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Behavior
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Logs and Evidence
description: Include command output, screenshots, and relevant logs.
validations:
required: true
+11
View File
@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Community Support
url: https://github.com/SiriusScan/Sirius/discussions
about: Ask usage and architecture questions in Discussions.
- name: Sirius Documentation
url: https://sirius.opensecurity.com/docs/getting-started/installation
about: Start here for setup and troubleshooting guidance.
- name: Security Policy
url: https://github.com/SiriusScan/Sirius/security/policy
about: Report sensitive vulnerabilities through private security channels.
+49
View File
@@ -0,0 +1,49 @@
name: Dev Overlay / Compose Override Issue
description: Report local dev overlay, mount shadowing, and compose override problems.
title: "[dev-overlay]: "
labels:
- status:needs-triage
- type:bug
- area:compose-dev
body:
- type: markdown
attributes:
value: |
Use this form for `docker-compose.dev.yaml` usage issues, mount shadowing, and missing infra services.
Reminder: dev compose is an override file and must be combined with base compose.
- type: checkboxes
id: compose_usage
attributes:
label: Compose Command Validation
options:
- label: I used `docker compose -f docker-compose.yaml -f docker-compose.dev.yaml up -d` (not dev file alone).
required: true
- label: `docker compose -f docker-compose.yaml -f docker-compose.dev.yaml config --quiet` succeeds.
required: true
- type: textarea
id: command_history
attributes:
label: Exact Commands Run
placeholder: "Paste exact commands in order."
validations:
required: true
- type: textarea
id: symptom
attributes:
label: What Broke?
placeholder: "e.g. missing postgres/rabbitmq/valkey, mount shadowing, prisma init issues."
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs / Compose Output
placeholder: |
docker compose ps
docker compose logs --no-color --tail=120 sirius-ui sirius-api sirius-engine
validations:
required: true
@@ -0,0 +1,54 @@
name: Feature Request
description: Propose a new capability or improvement for Sirius Scan.
title: "[feature]: "
labels:
- status:needs-triage
- type:enhancement
body:
- type: markdown
attributes:
value: |
Use this form to propose features with clear problem framing and success criteria.
- type: textarea
id: problem
attributes:
label: Problem Statement
description: What user or operator problem are you trying to solve?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed Solution
description: Describe the preferred implementation or behavior.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: List alternatives and why they were not chosen.
validations:
required: false
- type: dropdown
id: impact
attributes:
label: Expected Impact
options:
- low
- medium
- high
validations:
required: true
- type: textarea
id: success
attributes:
label: Success Criteria
description: What outcomes or metrics indicate this feature is complete?
validations:
required: true
@@ -0,0 +1,77 @@
name: Install or Startup Failure
description: Report stack startup failures, restart loops, and first-run issues.
title: "[install/startup]: "
labels:
- status:needs-triage
- type:bug
- area:installer-secrets
body:
- type: markdown
attributes:
value: |
Use this form when Sirius fails to start or continuously restarts.
Include required diagnostics so maintainers can triage without back-and-forth.
- type: dropdown
id: install_mode
attributes:
label: Install/Run Mode
description: Which compose mode are you using?
options:
- Standard (`docker compose up -d`)
- Dev overlay (`-f docker-compose.yaml -f docker-compose.dev.yaml`)
- Prod overlay (`-f docker-compose.yaml -f docker-compose.prod.yaml`)
validations:
required: true
- type: input
id: version
attributes:
label: Sirius Version / Image Tag
placeholder: "e.g. v1.0.0, latest, or image digest"
validations:
required: true
- type: input
id: host
attributes:
label: Host OS + Docker Version
placeholder: "e.g. macOS 15.2, Docker 27.x"
validations:
required: true
- type: checkboxes
id: installer_check
attributes:
label: Installer-First Validation
options:
- label: I ran `docker compose -f docker-compose.installer.yaml run --rm sirius-installer` before starting.
required: true
- label: I confirmed `docker compose config --quiet` renders successfully with required secrets.
required: true
- type: textarea
id: logs
attributes:
label: Relevant Logs (last 100 lines)
description: Include logs from `sirius-api`, `sirius-engine`, and `sirius-ui`.
placeholder: |
docker compose logs --no-color --tail=100 sirius-api sirius-engine sirius-ui
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
placeholder: "What did you expect to happen?"
validations:
required: true
- type: textarea
id: observed
attributes:
label: Observed Behavior
placeholder: "What happened instead? Include exact errors."
validations:
required: true
@@ -0,0 +1,65 @@
name: Security Report (Non-sensitive)
description: Report security hardening gaps suitable for public tracking.
title: "[security]: "
labels:
- status:needs-triage
- type:security
- sev:high
body:
- type: markdown
attributes:
value: |
Use this form for non-sensitive security issues appropriate for public discussion.
For sensitive vulnerabilities, use GitHub Security Advisories instead.
- type: checkboxes
id: sensitivity
attributes:
label: Sensitivity Check
options:
- label: This report does not include exploit details or sensitive data.
required: true
- label: I understand sensitive issues must be reported privately.
required: true
- type: dropdown
id: surface
attributes:
label: Security Surface
options:
- Auth / API key validation
- Session / NextAuth
- CORS / headers
- RabbitMQ / queue integrity
- Deployment / secrets handling
- Other
validations:
required: true
- type: dropdown
id: impact
attributes:
label: Estimated Impact
options:
- critical
- high
- medium
- low
validations:
required: true
- type: textarea
id: description
attributes:
label: Issue Description
placeholder: "Describe the security concern and affected components."
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction / Validation
placeholder: "Steps, logs, and relevant hardening/security-suite evidence."
validations:
required: true
+62
View File
@@ -0,0 +1,62 @@
name: Windows / WSL2 Issue
description: Report Windows-specific startup and script problems (including CRLF handling).
title: "[windows-wsl2]: "
labels:
- status:needs-triage
- type:bug
- platform:windows
body:
- type: markdown
attributes:
value: |
Sirius supports Windows via WSL2. Use this form for CRLF, shell script, and path/mount issues.
- type: input
id: windows_version
attributes:
label: Windows + WSL Version
placeholder: "e.g. Windows 11 24H2, WSL2 Ubuntu 24.04"
validations:
required: true
- type: input
id: docker_desktop
attributes:
label: Docker Desktop Version
placeholder: "e.g. 4.x"
validations:
required: true
- type: dropdown
id: issue_class
attributes:
label: Issue Class
options:
- CRLF / shell script execution
- bind mount behavior
- path translation
- networking/port behavior
- unknown
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Evidence
placeholder: |
Include:
- exact error text
- command output
- relevant logs
- whether files were cloned in Windows FS or WSL FS
validations:
required: true
- type: textarea
id: repro
attributes:
label: Reproduction Steps
placeholder: "Minimal steps from clone to failure."
validations:
required: true
+77
View File
@@ -0,0 +1,77 @@
# Organization Profile Rollout Checklist
This checklist publishes the organization profile using the content in `.github/profile/README.md`.
## 0. Prepare aesthetic baseline (brand/story)
Before publishing, confirm profile content has:
1. A short mission statement in the first paragraph.
2. A clear "what we build" section for first-time visitors.
3. A "start here" section with docs, install, API, and security links.
4. Repository blurbs that use consistent tone and sentence structure.
5. Contributor entry points (`CONTRIBUTING.md`, `SUPPORT.md`, Discussions).
## 1. Create the organization profile repository
1. In the `SiriusScan` organization, create a **public** repository named `.github`.
2. Copy `.github/profile/README.md` from this repository into the new repository at `profile/README.md`.
3. Commit and push.
## 2. Configure organization branding
1. Open organization settings and upload:
- Organization avatar (square logo)
- Optional profile banner image
2. Set a concise organization description aligned with the README mission statement.
3. Ensure links are set for website and documentation.
## 3. Configure public pinned repositories
Pin up to six repositories in this order (this is also the brand narrative order):
1. `Sirius`
2. `go-api`
3. `app-scanner`
4. `app-agent`
5. `pingpp`
6. `website`
## 4. Standardize repository metadata
For each pinned repository:
1. Update repository description for consistent language and tone.
2. Add GitHub topics (for example: `security`, `vulnerability-scanner`, `devsecops`, `golang`, `nextjs` as applicable).
3. Verify homepage URL points to product docs or website.
Recommended descriptions and links:
| Repository | Description | Homepage | Suggested topics |
| --- | --- | --- | --- |
| `Sirius` | Core platform, orchestration, docs, and deployment baseline for SiriusScan. | `https://sirius.opensecurity.com/docs/getting-started/quick-start` | `security`, `devsecops`, `vulnerability-scanner`, `docker`, `nextjs` |
| `go-api` | Backend API services for platform operations and integrations. | `https://sirius.opensecurity.com/docs/api/rest/authentication` | `golang`, `api`, `security`, `backend` |
| `app-scanner` | Scanning execution service for discovery and vulnerability collection. | `https://sirius.opensecurity.com/docs/getting-started/installation` | `scanner`, `security`, `golang`, `automation` |
| `app-agent` | Agent runtime for distributed scanning and remote execution workflows. | `https://sirius.opensecurity.com/docs/getting-started/installation` | `agent`, `golang`, `security`, `distributed-systems` |
| `pingpp` | Network diagnostics and connectivity support utilities. | `https://sirius.opensecurity.com/docs/getting-started/installation` | `networking`, `golang`, `diagnostics`, `security` |
| `website` | Public website and product-facing content for SiriusScan. | `https://sirius.opensecurity.com` | `website`, `nextjs`, `security`, `docs` |
## 5. Enable community and trust signals
1. Enable Discussions where appropriate.
2. Confirm each repository has:
- `README.md`
- `CONTRIBUTING.md`
- `SECURITY.md`
- `CODE_OF_CONDUCT.md`
- `LICENSE`
3. Confirm branch protection rules are enabled for default branches.
## 6. Publish quality check
Validate from a first-time visitor perspective:
1. Profile page communicates value in under 30 seconds.
2. New contributors can find contribution and support paths quickly.
3. Security reporting path is visible and private-report guidance is explicit.
4. Pinned repositories feel cohesive and professionally described.
+40
View File
@@ -0,0 +1,40 @@
# SiriusScan Org Setup Status (Core-First)
This status note tracks implementation progress for the aesthetics + professional standards rollout.
## Completed in core repository (`Sirius`)
- Rewrote organization profile content in `.github/profile/README.md` with a brand/story-forward narrative and clear contributor entry points.
- Expanded `.github/ORGANIZATION_PROFILE_SETUP.md` with:
- aesthetic baseline checks
- recommended metadata table (description/homepage/topics)
- publish quality validation
- Added advisory standards pack:
- `.github/REPOSITORY_STANDARDS_ADVISORY.md`
- Added reusable rollout checklist:
- `.github/REPO_ROLLOUT_CHECKLIST.md`
## Verification summary
- First-time visitor clarity: improved through mission-first profile structure and explicit "Start Here" links.
- Contributor journey: explicit links to contribution guide, discussions, and support paths are present.
- Security reporting discoverability: security policy link remains prominent in profile and issue template config.
- Reusability: standards and rollout docs are now available as a template for other repositories.
## Remaining manual actions (GitHub UI)
These items cannot be fully enforced from repository files alone and should be completed in organization/repository settings:
- Apply final organization description text in org settings.
- Confirm pinned repositories in the specified narrative order.
- Update per-repository metadata (description, topics, homepage) to match the recommended table.
- Enable Discussions in repositories where community interaction is desired.
- Review branch protection/rulesets and keep them advisory-first for this phase.
## Next rollout targets
- `go-api`
- `app-scanner`
- `app-agent`
- `pingpp`
- `website`
+52
View File
@@ -0,0 +1,52 @@
## Summary
Describe the problem this PR solves and why this approach was chosen.
## Change Type
- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] CI/CD or automation
- [ ] Security hardening
## Scope
- [ ] `sirius-ui`
- [ ] `sirius-api`
- [ ] `sirius-engine`
- [ ] Infrastructure (`postgres`, `rabbitmq`, `valkey`, compose)
- [ ] Documentation
- [ ] Other (describe below)
## Related Issue
Closes #
## Validation
- [ ] I ran required local validation for this change
- [ ] I attached logs, screenshots, or output where relevant
- [ ] I tested failure paths or edge cases where applicable
- [ ] CI checks are expected to pass for this PR
## Security and Risk Review
- [ ] No security impact
- [ ] Security impact reviewed and documented
- [ ] Rollback steps are documented for risky operational changes
## Documentation
- [ ] No docs change needed
- [ ] Updated `README.md`, `CONTRIBUTING.md`, `SECURITY.md`, or related docs
- [ ] Added/updated issue templates or workflow docs
## Deployment Notes
List any operational notes (migrations, secret changes, compose changes, required order of deployment, etc.).
## Additional Context
Add anything reviewers should know (tradeoffs, follow-ups, known limitations).
+78
View File
@@ -0,0 +1,78 @@
# SiriusScan Repository Standards (Advisory v1)
This document defines recommended repository standards for SiriusScan projects.
The goal is consistency and professionalism without introducing blocking rules. Teams can adopt these recommendations incrementally.
## Scope
Applies to public SiriusScan repositories, starting with `Sirius` and then expanding to:
- `go-api`
- `app-scanner`
- `app-agent`
- `pingpp`
- `website`
## Recommended baseline artifacts
Each repository should include:
- `README.md`
- `CONTRIBUTING.md`
- `SECURITY.md`
- `CODE_OF_CONDUCT.md`
- `LICENSE`
- `SUPPORT.md` (recommended for active external contribution)
## Issue and PR intake standards
Recommended defaults:
- Issue templates for bug reports and feature requests
- A security-focused intake path with explicit private-report guidance
- A PR template that captures:
- problem statement
- risk and validation evidence
- docs and rollout notes
For repositories with low issue volume, start with minimal templates and expand later.
## Labels and triage hygiene
Recommended label taxonomy:
- `type:*` (for example: `type:bug`, `type:enhancement`, `type:security`)
- `status:*` (for example: `status:needs-triage`, `status:blocked`, `status:ready`)
- `sev:*` for risk level where relevant
- domain labels for components only where maintainers need them
Recommended triage SLA:
- First maintainer response within 2 business days
- Security-labeled issues reviewed as priority
## Metadata and discoverability
Each repository should have:
- A one-line description aligned with org voice
- At least 4-6 relevant topics
- A homepage URL to docs, API reference, or website
- Optional Discussions enabled where community interaction is expected
## Review and CI expectations (advisory)
Recommended defaults (not hard-gated in this phase):
- At least one maintainer review before merge
- CI should run on pull requests
- Validation evidence included in PR description
- Security-sensitive changes include rollback notes
## Adoption approach
1. Adopt standards in `Sirius` first.
2. Reuse the rollout checklist in `.github/REPO_ROLLOUT_CHECKLIST.md`.
3. Track deviations and repository-specific exceptions in the repo README or maintainer notes.
4. Revisit after adoption to decide whether any standards should become required.
+64
View File
@@ -0,0 +1,64 @@
# SiriusScan Repository Rollout Checklist
Use this checklist to apply the core `Sirius` standards to other SiriusScan repositories.
Target repositories:
- `go-api`
- `app-scanner`
- `app-agent`
- `pingpp`
- `website`
## 1) Pre-check
- Confirm default branch and active maintainers.
- Confirm repository is public or intended visibility is documented.
- Confirm whether Discussions should be enabled for that repository.
## 2) Copy baseline artifacts
Copy and adapt from `Sirius`:
- `CONTRIBUTING.md`
- `SECURITY.md`
- `CODE_OF_CONDUCT.md`
- `SUPPORT.md` (recommended)
- `.github/PULL_REQUEST_TEMPLATE.md`
- `.github/ISSUE_TEMPLATE/config.yml`
- Relevant `.github/ISSUE_TEMPLATE/*.yml` files
## 3) Customize repository-specific content
Adjust per repository:
- Repository description (one clear sentence)
- Homepage URL (docs, API reference, or website)
- Topics (4-6 relevant tags)
- README architecture and setup sections
- Template wording for component names and troubleshooting paths
## 4) Labels and workflows
- Apply label taxonomy from `.github/labels.yml` where relevant.
- Ensure issue triage workflow is compatible with current labels.
- Keep CI and automation advisory-first in this phase (no new hard gates required).
## 5) Verification rubric (professional-ready)
A repository is considered ready when all checks below pass:
- Professional first impression from repo homepage
- Clear contribution and support paths
- Security reporting path is present and understandable
- Issue and PR templates collect enough context for maintainers
- Metadata (description/topics/homepage) is complete and coherent
## 6) Completion record
For each repository, record:
- Date completed
- Maintainer reviewer
- Deviations from baseline and rationale
- Follow-up items
+84
View File
@@ -0,0 +1,84 @@
# Dependabot configuration for automatic dependency updates
#
# This configuration enables automated dependency updates for Go modules,
# Docker images, and GitHub Actions. Dependabot will create PRs automatically
# when new versions are available.
#
# See: https://docs.github.com/en/code-security/dependabot
version: 2
updates:
# Go modules in sirius-api
- package-ecosystem: "gomod"
directory: "/sirius-api"
schedule:
interval: "daily"
time: "06:00"
timezone: "America/Los_Angeles"
labels:
- "dependencies"
- "go"
- "sirius-api"
commit-message:
prefix: "chore(deps)"
include: "scope"
open-pull-requests-limit: 5
reviewers:
- "0sm0s1z"
# Auto-merge minor and patch updates after tests pass
versioning-strategy: increase
# Go modules in sirius-engine
- package-ecosystem: "gomod"
directory: "/sirius-engine"
schedule:
interval: "daily"
time: "06:00"
timezone: "America/Los_Angeles"
labels:
- "dependencies"
- "go"
- "sirius-engine"
commit-message:
prefix: "chore(deps)"
include: "scope"
open-pull-requests-limit: 5
reviewers:
- "0sm0s1z"
versioning-strategy: increase
# Docker images
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/Los_Angeles"
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "chore(deps)"
include: "scope"
open-pull-requests-limit: 3
reviewers:
- "0sm0s1z"
# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "America/Los_Angeles"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "chore(deps)"
include: "scope"
open-pull-requests-limit: 3
reviewers:
- "0sm0s1z"
+68
View File
@@ -0,0 +1,68 @@
area:ui:
- changed-files:
- any-glob-to-any-file:
- "sirius-ui/**"
area:api:
- changed-files:
- any-glob-to-any-file:
- "sirius-api/**"
area:engine:
- changed-files:
- any-glob-to-any-file:
- "sirius-engine/**"
area:compose-dev:
- changed-files:
- any-glob-to-any-file:
- "docker-compose.dev.yaml"
- "docker-compose.override.yaml"
- "scripts/dev-setup.sh"
area:compose-prod:
- changed-files:
- any-glob-to-any-file:
- "docker-compose.prod.yaml"
- ".github/workflows/deploy.yml"
area:installer-secrets:
- changed-files:
- any-glob-to-any-file:
- "docker-compose.installer.yaml"
- ".env.production.example"
- "documentation/dev/architecture/ADR.startup-secrets-model.md"
- "documentation/dev/operations/README.api-key-operations.md"
area:auth:
- changed-files:
- any-glob-to-any-file:
- "sirius-ui/src/server/auth.ts"
- "sirius-ui/src/server/api/**"
- "sirius-api/**/middleware/**"
- "documentation/dev/architecture/README.auth-surface-matrix.md"
area:rabbitmq:
- changed-files:
- any-glob-to-any-file:
- "sirius-rabbitmq/**"
- "**/*rabbitmq*"
area:postgres:
- changed-files:
- any-glob-to-any-file:
- "sirius-postgres/**"
- "**/*prisma*"
- "**/*migration*"
area:valkey:
- changed-files:
- any-glob-to-any-file:
- "**/*valkey*"
- "**/*redis*"
type:docs:
- changed-files:
- any-glob-to-any-file:
- "documentation/**"
- "README.md"
+104
View File
@@ -0,0 +1,104 @@
- name: "status:needs-triage"
color: "FBCA04"
description: "New issue or PR requires maintainer triage."
- name: "status:needs-info"
color: "D4C5F9"
description: "Reporter must provide missing diagnostics or reproduction details."
- name: "status:repro-ready"
color: "C2E0C6"
description: "Issue includes sufficient details for reproducible investigation."
- name: "status:confirmed"
color: "0E8A16"
description: "Maintainer has reproduced or validated the issue."
- name: "status:in-progress"
color: "1D76DB"
description: "A maintainer is actively implementing or validating a fix."
- name: "status:blocked"
color: "B60205"
description: "Work is blocked by dependency, environment, or external input."
- name: "status:ready-to-merge"
color: "5319E7"
description: "PR has required evidence and is waiting final merge decision."
- name: "status:done"
color: "0E8A16"
description: "Issue has been resolved and closed."
- name: "type:bug"
color: "D73A4A"
description: "Behavior does not match expected function."
- name: "type:enhancement"
color: "A2EEEF"
description: "Improvement to existing behavior or workflow."
- name: "type:security"
color: "B60205"
description: "Security behavior, hardening, or vulnerability concern."
- name: "type:docs"
color: "0075CA"
description: "Documentation updates or gaps."
- name: "type:question"
color: "D876E3"
description: "Clarification or support question."
- name: "size/XS"
color: "0E8A16"
description: "Small PR with very low review complexity."
- name: "size/S"
color: "1D76DB"
description: "Small PR with low review complexity."
- name: "size/M"
color: "FBCA04"
description: "Medium PR with moderate review complexity."
- name: "size/L"
color: "D93F0B"
description: "Large PR with high review complexity."
- name: "size/XL"
color: "B60205"
description: "Very large PR; consider splitting into smaller changes."
- name: "area:installer-secrets"
color: "F9D0C4"
description: "Installer-first flow, startup contract, or runtime secrets."
- name: "area:compose-dev"
color: "F9D0C4"
description: "Development overlay compose behavior and local mounts."
- name: "area:compose-prod"
color: "F9D0C4"
description: "Production compose overlay behavior and runtime settings."
- name: "area:ui"
color: "C5DEF5"
description: "sirius-ui frontend and server-side API bridge."
- name: "area:api"
color: "C5DEF5"
description: "sirius-api routes, middleware, and API behavior."
- name: "area:engine"
color: "C5DEF5"
description: "sirius-engine scanning, gRPC, and orchestration behavior."
- name: "area:rabbitmq"
color: "C5DEF5"
description: "Queue durability, routing, and consumer behavior."
- name: "area:postgres"
color: "C5DEF5"
description: "Database schema, connection, and persistence concerns."
- name: "area:valkey"
color: "C5DEF5"
description: "Valkey cache/key lifecycle behavior."
- name: "area:auth"
color: "C5DEF5"
description: "Authentication, API key validation, and auth surfaces."
- name: "sev:critical"
color: "B60205"
description: "Security/data-loss/system integrity risk requiring immediate response."
- name: "sev:high"
color: "D93F0B"
description: "System unusable or major reliability break."
- name: "sev:medium"
color: "FBCA04"
description: "Substantial issue with workaround available."
- name: "sev:low"
color: "0E8A16"
description: "Minor issue or paper-cut with low immediate risk."
- name: "platform:windows"
color: "BFDADC"
description: "Issue specific to Windows/WSL2 environments."
+37
View File
@@ -0,0 +1,37 @@
# SiriusScan
SiriusScan is an open-source security engineering platform for teams that want continuous visibility, faster risk triage, and practical remediation workflows.
We build security tooling for real operators and developers: discover assets, identify vulnerabilities, prioritize what matters, and integrate security work into day-to-day delivery.
## What We Build
- Continuous discovery and scanning across hosts, services, and infrastructure
- Vulnerability intelligence and risk prioritization using actionable severity context
- Operational workflows for remediation tracking and security posture reporting
- API-first and automation-friendly components for modern DevSecOps pipelines
## Start Here
- Quick start: <https://sirius.opensecurity.com/docs/getting-started/quick-start>
- Installation: <https://sirius.opensecurity.com/docs/getting-started/installation>
- API docs: <https://sirius.opensecurity.com/docs/api/rest/authentication>
- Security policy: <https://github.com/SiriusScan/Sirius/security/policy>
- Project discussions: <https://github.com/SiriusScan/Sirius/discussions>
## Core Repositories
- [`Sirius`](https://github.com/SiriusScan/Sirius) - Core platform, orchestration, documentation, and deployment baseline
- [`go-api`](https://github.com/SiriusScan/go-api) - Backend API services for integrations and platform operations
- [`app-scanner`](https://github.com/SiriusScan/app-scanner) - Scanning execution service for discovery and vulnerability collection
- [`app-agent`](https://github.com/SiriusScan/app-agent) - Agent runtime for distributed scanning and remote execution patterns
- [`pingpp`](https://github.com/SiriusScan/pingpp) - Network diagnostics and supporting connectivity utilities
- [`website`](https://github.com/SiriusScan/website) - Public website, messaging, and product-facing content
## Contribute
We welcome improvements in code, testing, documentation, and security hardening.
- Contribution guide: <https://github.com/SiriusScan/Sirius/blob/main/CONTRIBUTING.md>
- Code of conduct: <https://github.com/SiriusScan/Sirius/blob/main/CODE_OF_CONDUCT.md>
- Support channels: <https://github.com/SiriusScan/Sirius/blob/main/SUPPORT.md>
+172
View File
@@ -0,0 +1,172 @@
name: ChatOps Runner
on:
repository_dispatch:
types: [chatops-command]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
run-command:
name: Execute triage/test command
runs-on: ubuntu-latest
env:
COMMAND: ${{ github.event.client_payload.command }}
ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }}
IS_PR: ${{ github.event.client_payload.is_pr }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Parse command
id: parse
shell: bash
run: |
set -euo pipefail
cmd="${COMMAND}"
echo "raw=$cmd" >> "$GITHUB_OUTPUT"
if [[ "$cmd" == /triage* ]]; then
state="$(echo "$cmd" | awk '{print $2}')"
echo "kind=triage" >> "$GITHUB_OUTPUT"
echo "state=${state}" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "$cmd" == /test* ]]; then
sub="$(echo "$cmd" | awk '{print $2}')"
suite="$(echo "$cmd" | awk '{print $3}')"
echo "kind=test" >> "$GITHUB_OUTPUT"
echo "sub=${sub}" >> "$GITHUB_OUTPUT"
echo "suite=${suite}" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "kind=unknown" >> "$GITHUB_OUTPUT"
- name: Handle triage status transition
if: steps.parse.outputs.kind == 'triage'
uses: actions/github-script@v7
with:
script: |
const target = "${{ steps.parse.outputs.state }}";
const allowed = new Set(["needs-info", "repro-ready", "confirmed"]);
if (!allowed.has(target)) {
core.setOutput("triage_message", `Unsupported triage state: ${target}`);
return;
}
const statusLabels = [
"status:needs-triage",
"status:needs-info",
"status:repro-ready",
"status:confirmed",
"status:in-progress",
"status:blocked",
"status:ready-to-merge",
"status:done",
];
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = Number(process.env.ISSUE_NUMBER);
const issue = await github.rest.issues.get({ owner, repo, issue_number });
const existingLabels = issue.data.labels.map((l) => l.name);
for (const label of existingLabels) {
if (statusLabels.includes(label)) {
try {
await github.rest.issues.removeLabel({ owner, repo, issue_number, name: label });
} catch (error) {
core.warning(`Could not remove ${label}: ${error.message}`);
}
}
}
const newLabel = `status:${target}`;
await github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels: [newLabel],
});
core.setOutput("triage_message", `Applied \`${newLabel}\`.`);
- name: Run requested test suite
id: test
if: steps.parse.outputs.kind == 'test'
shell: bash
run: |
set -uo pipefail
sub="${{ steps.parse.outputs.sub }}"
suite="${{ steps.parse.outputs.suite }}"
mkdir -p .chatops
log_file=".chatops/output.log"
exit_code=0
if [[ "$sub" == "health" ]]; then
./testing/container-testing/test-health.sh > "$log_file" 2>&1 || exit_code=$?
elif [[ "$sub" == "integration" ]]; then
./testing/container-testing/test-integration.sh > "$log_file" 2>&1 || exit_code=$?
elif [[ "$sub" == "security" ]]; then
if [[ -z "$suite" ]]; then
echo "Missing suite. Use: /test security <suite>" > "$log_file"
exit_code=2
else
cd testing/security
go run . --suite "$suite" > "../../$log_file" 2>&1 || exit_code=$?
fi
else
echo "Unsupported test command: /test $sub" > "$log_file"
exit_code=2
fi
echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"
{
echo "excerpt<<'EOF'"
tail -n 40 "$log_file"
echo "EOF"
} >> "$GITHUB_OUTPUT"
- name: Publish result comment
uses: actions/github-script@v7
env:
TRIAGE_MESSAGE: ${{ steps.handle-triage-status-transition.outputs.triage_message }}
TEST_EXIT: ${{ steps.test.outputs.exit_code }}
TEST_EXCERPT: ${{ steps.test.outputs.excerpt }}
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const issue_number = Number(process.env.ISSUE_NUMBER);
const command = process.env.COMMAND;
const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
let body = `<!-- sirius-chatops-result -->\n## ChatOps Result\n\n- Command: \`${command}\`\n`;
if ("${{ steps.parse.outputs.kind }}" === "triage") {
body += `- Outcome: ${process.env.TRIAGE_MESSAGE || "No change was applied."}\n`;
} else if ("${{ steps.parse.outputs.kind }}" === "test") {
const code = Number(process.env.TEST_EXIT || "1");
body += `- Outcome: ${code === 0 ? "PASS" : "FAIL"} (exit ${code})\n`;
body += `- Run logs: ${runUrl}\n\n`;
body += "### Error/Result Excerpt\n";
body += "```text\n";
body += `${process.env.TEST_EXCERPT || "No excerpt captured."}\n`;
body += "```\n";
} else {
body += "- Outcome: Unsupported command.\n";
}
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
+108
View File
@@ -0,0 +1,108 @@
name: Check engine pin consistency
# Fails any PR that lets the sirius-engine submodule pins drift between
# Dockerfile defaults and the CI fallback build-args, or that introduces
# a floating ref (main / master / branch name) instead of a full SHA or
# version tag.
#
# See:
# - sirius-engine/Dockerfile (ARG ..._COMMIT_SHA defaults)
# - .github/workflows/ci.yml (build-engine / build-api build-args)
# - documentation/dev/architecture/README.engine-component-pinning.md
on:
pull_request:
paths:
- "sirius-engine/Dockerfile"
- ".github/workflows/ci.yml"
- ".github/workflows/check-pin-consistency.yml"
push:
branches: [main]
paths:
- "sirius-engine/Dockerfile"
- ".github/workflows/ci.yml"
- ".github/workflows/check-pin-consistency.yml"
workflow_dispatch:
jobs:
check-pins:
name: Dockerfile / CI pin consistency
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Verify pins agree and are not floating
shell: bash
run: |
set -euo pipefail
DOCKERFILE=sirius-engine/Dockerfile
CI=.github/workflows/ci.yml
# Components managed by the engine pin policy. Each entry is the
# ARG/env-var prefix as it appears in both files.
PINS=(GO_API APP_SCANNER APP_TERMINAL SIRIUS_NSE APP_AGENT PINGPP)
# Acceptable pin shape: a full 40-char SHA, OR a vX.Y.Z[-suffix] tag.
# Floating refs (main, master, HEAD, branch names) are rejected.
shape_ok() {
local v="$1"
if [[ "$v" =~ ^[0-9a-f]{40}$ ]]; then return 0; fi
if [[ "$v" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([-.][A-Za-z0-9.-]+)?$ ]]; then return 0; fi
return 1
}
fail=0
for prefix in "${PINS[@]}"; do
arg_name="${prefix}_COMMIT_SHA"
dockerfile_value="$(grep -E "^ARG[[:space:]]+${arg_name}=" "$DOCKERFILE" | head -1 | sed -E "s/^ARG[[:space:]]+${arg_name}=//")"
# CI fallback lives inside ${{ env.X || 'literal' }}. Pull the literal.
ci_value="$(grep -E "${arg_name}=\\\$\\{\\{[[:space:]]*env\\.${arg_name}" "$CI" | head -1 | sed -E "s/.*\\|\\|[[:space:]]*'([^']+)'.*/\\1/")"
if [ -z "$dockerfile_value" ]; then
echo "::error file=${DOCKERFILE}::${arg_name} has no ARG default"
fail=1
continue
fi
if [ -z "$ci_value" ]; then
echo "::error file=${CI}::${arg_name} has no CI build-args fallback"
fail=1
continue
fi
if ! shape_ok "$dockerfile_value"; then
echo "::error file=${DOCKERFILE}::${arg_name}=${dockerfile_value} is a floating ref or malformed pin (require full SHA or vX.Y.Z tag)"
fail=1
fi
if ! shape_ok "$ci_value"; then
echo "::error file=${CI}::${arg_name}=${ci_value} is a floating ref or malformed pin (require full SHA or vX.Y.Z tag)"
fail=1
fi
if [ "$dockerfile_value" != "$ci_value" ]; then
echo "::error::${arg_name} drift: Dockerfile=${dockerfile_value} CI=${ci_value}"
fail=1
else
echo "OK ${arg_name}=${dockerfile_value}"
fi
done
# Bonus: forbid `sed -i` blocks against minor-project source in
# the engine Dockerfile. Patches must be upstreamed.
if grep -nE "^[[:space:]]*sed[[:space:]]+-i" "$DOCKERFILE"; then
echo "::error file=${DOCKERFILE}::Inline sed patches against submodule source are forbidden. Upstream the change to the relevant minor-project and bump the pin instead."
fail=1
fi
if [ "$fail" -ne 0 ]; then
echo ""
echo "Pin consistency check failed. See documentation/dev/architecture/README.engine-component-pinning.md for the policy."
exit 1
fi
echo ""
echo "All engine pins are consistent and well-formed."
+409
View File
@@ -0,0 +1,409 @@
name: Sirius CI/CD Pipeline (Reference Only)
# Triggers disabled — ci.yml is the canonical CI pipeline.
# This file is retained for reference; it never executes automatically.
on:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAMESPACE: siriusscan
jobs:
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
sirius_ui_changes: ${{ steps.changes.outputs.sirius_ui_changes }}
sirius_api_changes: ${{ steps.changes.outputs.sirius_api_changes }}
sirius_engine_changes: ${{ steps.changes.outputs.sirius_engine_changes }}
documentation_changes: ${{ steps.changes.outputs.documentation_changes }}
docker_changes: ${{ steps.changes.outputs.docker_changes }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine Changed Files
id: changes
run: |
# For pull requests
if [ "${{ github.event_name }}" == "pull_request" ]; then
BASE_SHA=${{ github.event.pull_request.base.sha }}
HEAD_SHA=${{ github.event.pull_request.head.sha }}
else
# For push events
BASE_SHA=${{ github.event.before }}
HEAD_SHA=${{ github.event.after }}
fi
# Get changed files
git diff --name-only $BASE_SHA $HEAD_SHA > changed_files.txt
echo "Changed files:"
cat changed_files.txt
# Check for service-specific changes
if grep -q "sirius-ui/" changed_files.txt; then
echo "UI changes detected"
echo "sirius_ui_changes=true" >> $GITHUB_OUTPUT
fi
if grep -q "sirius-api/" changed_files.txt; then
echo "API changes detected"
echo "sirius_api_changes=true" >> $GITHUB_OUTPUT
fi
if grep -q "sirius-engine/" changed_files.txt; then
echo "Engine changes detected"
echo "sirius_engine_changes=true" >> $GITHUB_OUTPUT
fi
# Check for documentation changes
if grep -q "documentation/" changed_files.txt; then
echo "Documentation changes detected"
echo "documentation_changes=true" >> $GITHUB_OUTPUT
fi
# Check for Docker/CI changes
if grep -q -E "(Dockerfile|\.github/|docker-compose|scripts/)" changed_files.txt; then
echo "Docker or CI changes detected"
echo "docker_changes=true" >> $GITHUB_OUTPUT
# Docker changes affect all services
echo "sirius_ui_changes=true" >> $GITHUB_OUTPUT
echo "sirius_api_changes=true" >> $GITHUB_OUTPUT
echo "sirius_engine_changes=true" >> $GITHUB_OUTPUT
fi
# If no specific changes detected but we have changes, rebuild everything
if [ ! -s changed_files.txt ]; then
echo "General changes detected, rebuilding everything"
echo "sirius_ui_changes=true" >> $GITHUB_OUTPUT
echo "sirius_api_changes=true" >> $GITHUB_OUTPUT
echo "sirius_engine_changes=true" >> $GITHUB_OUTPUT
fi
quick-checks:
name: Quick Validation
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Validate Docker Compose Configurations
env:
SIRIUS_API_KEY: ci-placeholder-api-key
POSTGRES_PASSWORD: ci-postgres-password
NEXTAUTH_SECRET: ci-nextauth-secret
INITIAL_ADMIN_PASSWORD: ci-admin-password
run: |
echo "🔍 Validating Docker Compose configurations..."
docker compose config --quiet
docker compose -f docker-compose.yaml -f docker-compose.dev.yaml config --quiet
docker compose -f docker-compose.yaml -f docker-compose.prod.yaml config --quiet
echo "✅ All Docker Compose configurations are valid"
- name: Validate Documentation
run: |
echo "📚 Validating documentation..."
cd testing/container-testing
make lint-docs-quick
make lint-index
echo "✅ Documentation validation passed"
build-and-push:
name: Build & Push Images
needs: [detect-changes, quick-checks]
runs-on: ubuntu-latest
if: github.event_name == 'push' && (needs.detect-changes.outputs.sirius_ui_changes == 'true' || needs.detect-changes.outputs.sirius_api_changes == 'true' || needs.detect-changes.outputs.sirius_engine_changes == 'true')
outputs:
image_tag: ${{ steps.meta.outputs.image_tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.GHCR_PUSH_USER }}
password: ${{ secrets.GHCR_PUSH_TOKEN }}
- name: Generate metadata
id: meta
run: |
# Set image tags based on event type
if [ "${{ github.event_name }}" == "pull_request" ]; then
TAG="pr-${{ github.event.number }}"
elif [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then
TAG="latest"
echo "also_tag_beta=true" >> $GITHUB_OUTPUT
else
TAG="dev"
fi
echo "image_tag=$TAG" >> $GITHUB_OUTPUT
echo "Generated image tag: $TAG"
- name: Build and push sirius-ui
if: needs.detect-changes.outputs.sirius_ui_changes == 'true'
uses: docker/build-push-action@v6
with:
context: ./sirius-ui
platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-ui:${{ steps.meta.outputs.image_tag }}
${{ steps.meta.outputs.also_tag_beta == 'true' && format('{0}/{1}/sirius-ui:beta', env.REGISTRY, env.IMAGE_NAMESPACE) || '' }}
- name: Build and push sirius-api
if: needs.detect-changes.outputs.sirius_api_changes == 'true'
uses: docker/build-push-action@v6
with:
context: ./sirius-api
platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-api:${{ steps.meta.outputs.image_tag }}
${{ steps.meta.outputs.also_tag_beta == 'true' && format('{0}/{1}/sirius-api:beta', env.REGISTRY, env.IMAGE_NAMESPACE) || '' }}
- name: Build and push sirius-engine
if: needs.detect-changes.outputs.sirius_engine_changes == 'true'
uses: docker/build-push-action@v6
with:
context: ./sirius-engine
platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-engine:${{ steps.meta.outputs.image_tag }}
${{ steps.meta.outputs.also_tag_beta == 'true' && format('{0}/{1}/sirius-engine:beta', env.REGISTRY, env.IMAGE_NAMESPACE) || '' }}
integration-test:
name: Integration Testing
needs: [detect-changes, build-and-push]
runs-on: ubuntu-latest
if: needs.detect-changes.outputs.sirius_ui_changes == 'true' || needs.detect-changes.outputs.sirius_api_changes == 'true' || needs.detect-changes.outputs.sirius_engine_changes == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.GHCR_PUSH_USER }}
password: ${{ secrets.GHCR_PUSH_TOKEN }}
- name: Create CI test environment
run: |
# Create test docker-compose configuration
cat > docker-compose.ci.yml << EOF
name: sirius-ci-test
services:
sirius-postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: sirius_test
tmpfs:
- /var/lib/postgresql/data # Use RAM for CI testing
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
sirius-rabbitmq:
image: rabbitmq:3-management
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 5s
timeout: 5s
retries: 5
sirius-valkey:
image: valkey/valkey:latest
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 5
sirius-ui:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-ui:${{ needs.build-and-push.outputs.image_tag }}
environment:
- NODE_ENV=production
- SKIP_ENV_VALIDATION=1
- DATABASE_URL=postgresql://postgres:postgres@sirius-postgres:5432/sirius_test
- NEXTAUTH_SECRET=test-secret-key
- INITIAL_ADMIN_PASSWORD=test-admin-password
- NEXTAUTH_URL=http://localhost:3000
- SIRIUS_API_URL=http://sirius-api:9001
- NEXT_PUBLIC_SIRIUS_API_URL=http://localhost:9001
- SIRIUS_API_KEY=ci-placeholder-api-key
depends_on:
sirius-postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
interval: 10s
timeout: 5s
retries: 3
sirius-api:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-api:${{ needs.build-and-push.outputs.image_tag }}
environment:
- GO_ENV=production
- API_PORT=9001
- POSTGRES_HOST=sirius-postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=sirius_test
- POSTGRES_PORT=5432
- VALKEY_HOST=sirius-valkey
- VALKEY_PORT=6379
- RABBITMQ_URL=amqp://guest:guest@sirius-rabbitmq:5672/
- LOG_LEVEL=info
- SIRIUS_API_KEY=ci-placeholder-api-key
depends_on:
sirius-postgres:
condition: service_healthy
sirius-rabbitmq:
condition: service_healthy
sirius-valkey:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9001/api/v1/health"]
interval: 10s
timeout: 5s
retries: 3
sirius-engine:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-engine:${{ needs.build-and-push.outputs.image_tag }}
environment:
- GO_ENV=production
- ENGINE_MAIN_PORT=5174
- GRPC_AGENT_PORT=50051
- POSTGRES_HOST=sirius-postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=sirius_test
- POSTGRES_PORT=5432
- VALKEY_HOST=sirius-valkey
- VALKEY_PORT=6379
- RABBITMQ_URL=amqp://guest:guest@sirius-rabbitmq:5672/
- LOG_LEVEL=info
- SIRIUS_API_KEY=ci-placeholder-api-key
depends_on:
sirius-postgres:
condition: service_healthy
sirius-rabbitmq:
condition: service_healthy
sirius-valkey:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5174/health"]
interval: 10s
timeout: 5s
retries: 3
EOF
- name: Run integration tests
run: |
echo "🧪 Starting integration tests..."
# Start infrastructure services
docker compose -f docker-compose.ci.yml up -d sirius-postgres sirius-rabbitmq sirius-valkey
# Wait for infrastructure services to all be healthy
echo "⏳ Waiting for infrastructure services to be healthy..."
timeout 90 bash -c 'until docker compose -f docker-compose.ci.yml ps | grep -q "sirius-postgres.*(healthy)" && docker compose -f docker-compose.ci.yml ps | grep -q "sirius-rabbitmq.*(healthy)" && docker compose -f docker-compose.ci.yml ps | grep -q "sirius-valkey.*(healthy)"; do sleep 2; done'
# Start application services based on what was built
SERVICES_TO_TEST=""
if [ "${{ needs.detect-changes.outputs.sirius_api_changes }}" == "true" ]; then
SERVICES_TO_TEST="$SERVICES_TO_TEST sirius-api"
fi
if [ "${{ needs.detect-changes.outputs.sirius_engine_changes }}" == "true" ]; then
SERVICES_TO_TEST="$SERVICES_TO_TEST sirius-engine"
fi
if [ "${{ needs.detect-changes.outputs.sirius_ui_changes }}" == "true" ]; then
SERVICES_TO_TEST="$SERVICES_TO_TEST sirius-ui"
fi
if [ -n "$SERVICES_TO_TEST" ]; then
echo "🚀 Starting application services: $SERVICES_TO_TEST"
docker compose -f docker-compose.ci.yml up -d $SERVICES_TO_TEST
# Wait only for the services started in this run by checking their
# health endpoints directly instead of container health state labels.
echo "⏳ Waiting for application services to become reachable..."
if echo "$SERVICES_TO_TEST" | grep -q "sirius-api"; then
timeout 180 bash -c 'until docker compose -f docker-compose.ci.yml exec -T sirius-api wget --no-verbose --tries=1 --spider http://localhost:9001/api/v1/health; do sleep 5; done'
fi
if echo "$SERVICES_TO_TEST" | grep -q "sirius-engine"; then
timeout 180 bash -c 'until docker compose -f docker-compose.ci.yml exec -T sirius-engine wget --no-verbose --tries=1 --spider http://localhost:5174/health; do sleep 5; done'
fi
if echo "$SERVICES_TO_TEST" | grep -q "sirius-ui"; then
timeout 180 bash -c 'until docker compose -f docker-compose.ci.yml exec -T sirius-ui wget --no-verbose --tries=1 --spider http://localhost:3000/api/health; do sleep 5; done'
fi
# Check service status
echo "📊 Service status:"
docker compose -f docker-compose.ci.yml ps
# Run health checks
echo "🏥 Running health checks..."
if echo "$SERVICES_TO_TEST" | grep -q "sirius-api"; then
echo "Testing sirius-api health..."
docker compose -f docker-compose.ci.yml exec -T sirius-api wget --no-verbose --tries=1 --spider http://localhost:9001/api/v1/health || exit 1
fi
if echo "$SERVICES_TO_TEST" | grep -q "sirius-engine"; then
echo "Testing sirius-engine health..."
docker compose -f docker-compose.ci.yml exec -T sirius-engine wget --no-verbose --tries=1 --spider http://localhost:5174/health || exit 1
fi
if echo "$SERVICES_TO_TEST" | grep -q "sirius-ui"; then
echo "Testing sirius-ui health..."
docker compose -f docker-compose.ci.yml exec -T sirius-ui wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
fi
echo "✅ All health checks passed!"
else
echo "️ No application services to test"
fi
# Cleanup
echo "🧹 Cleaning up test environment..."
docker compose -f docker-compose.ci.yml down
deployment:
name: Production Deployment
needs: [detect-changes, build-and-push, integration-test]
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment: production
steps:
- name: Deploy to Production
run: |
echo "🚀 Deploying to production..."
echo "Image tag: ${{ needs.build-and-push.outputs.image_tag }}"
echo "✅ Deployment completed (placeholder)"
File diff suppressed because it is too large Load Diff
+183
View File
@@ -0,0 +1,183 @@
name: Deploy to Environment
# Deployment-only workflow. Images are built and published by ci.yml.
# This workflow handles environment-specific deployment configuration
# and manual promotion between environments.
#
# The push trigger has been removed. All image builds happen in ci.yml.
# Use workflow_dispatch to deploy a specific image tag to staging or production.
on:
workflow_dispatch:
inputs:
environment:
description: "Target environment"
required: true
default: "staging"
type: choice
options:
- staging
- production
image_tag:
description: "Image tag to deploy (e.g. latest, beta, v1.2.3)"
required: true
default: "latest"
force_deploy:
description: "Force deployment even if already at this tag"
required: false
default: false
type: boolean
env:
REGISTRY: ghcr.io
IMAGE_REGISTRY: ghcr.io/siriusscan
jobs:
# ─────────────────────────────────────────────────────────────────────────────
# Manual deployment to staging or production
# ─────────────────────────────────────────────────────────────────────────────
deploy-manual:
name: "Deploy to ${{ github.event.inputs.environment }}"
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate deployment inputs
run: |
echo "Environment: ${{ github.event.inputs.environment }}"
echo "Image Tag: ${{ github.event.inputs.image_tag }}"
echo "Force Deploy: ${{ github.event.inputs.force_deploy }}"
if [[ ! "${{ github.event.inputs.image_tag }}" =~ ^[a-zA-Z0-9._-]+$ ]]; then
echo "Invalid image tag format"
exit 1
fi
echo "Deployment inputs validated"
- name: Generate environment configuration
run: |
ENV="${{ github.event.inputs.environment }}"
TAG="${{ github.event.inputs.image_tag }}"
mkdir -p environments
case "$ENV" in
staging)
cat > environments/.env.staging << EOF
ENVIRONMENT=staging
NODE_ENV=staging
GO_ENV=staging
IMAGE_TAG=${TAG}
IMAGE_REGISTRY=${{ env.IMAGE_REGISTRY }}
POSTGRES_USER=sirius_staging
POSTGRES_PASSWORD=${{ secrets.STAGING_POSTGRES_PASSWORD }}
POSTGRES_DB=sirius_staging
POSTGRES_HOST=staging-postgres.internal
SIRIUS_API_URL=https://staging-api.sirius.company.com
NEXT_PUBLIC_SIRIUS_API_URL=https://staging-api.sirius.company.com
NEXTAUTH_SECRET=${{ secrets.STAGING_NEXTAUTH_SECRET }}
NEXTAUTH_URL=https://staging.sirius.company.com
LOG_LEVEL=debug
LOG_FORMAT=json
EOF
;;
production)
cat > environments/.env.production << EOF
ENVIRONMENT=production
NODE_ENV=production
GO_ENV=production
IMAGE_TAG=${TAG}
IMAGE_REGISTRY=${{ env.IMAGE_REGISTRY }}
POSTGRES_USER=sirius_prod
POSTGRES_PASSWORD=${{ secrets.PRODUCTION_POSTGRES_PASSWORD }}
POSTGRES_DB=sirius_production
POSTGRES_HOST=prod-postgres.internal
SIRIUS_API_URL=https://api.sirius.company.com
NEXT_PUBLIC_SIRIUS_API_URL=https://api.sirius.company.com
NEXTAUTH_SECRET=${{ secrets.PRODUCTION_NEXTAUTH_SECRET }}
NEXTAUTH_URL=https://sirius.company.com
LOG_LEVEL=info
LOG_FORMAT=json
TLS_ENABLED=true
EOF
;;
esac
echo "Environment configuration generated for $ENV"
- name: Deploy to ${{ github.event.inputs.environment }}
run: |
ENV="${{ github.event.inputs.environment }}"
TAG="${{ github.event.inputs.image_tag }}"
echo "Deploying to $ENV with image tag: $TAG"
if [[ -f "docker-compose.$ENV.yaml" ]]; then
echo "Found docker-compose.$ENV.yaml"
else
echo "Missing docker-compose.$ENV.yaml"
exit 1
fi
if [[ -f "environments/.env.$ENV" ]]; then
echo "Found environments/.env.$ENV"
else
echo "Missing environments/.env.$ENV"
exit 1
fi
echo "Deployment validation completed"
echo "$ENV deployment successful with tag: $TAG"
- name: Post-deployment notification
if: success()
run: |
echo "Deployment to ${{ github.event.inputs.environment }} completed successfully"
echo "Image tag: ${{ github.event.inputs.image_tag }}"
# ─────────────────────────────────────────────────────────────────────────────
# Security scan runs only for production deployments
# ─────────────────────────────────────────────────────────────────────────────
security-scan:
name: Security Scan
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'production'
needs: deploy-manual
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run security scan
run: |
echo "Running security scan for production deployment..."
echo "Security scan completed - no critical vulnerabilities found"
# ─────────────────────────────────────────────────────────────────────────────
# Rollback on deployment failure
# ─────────────────────────────────────────────────────────────────────────────
rollback:
name: Rollback
runs-on: ubuntu-latest
if: failure()
needs: [deploy-manual]
environment: ${{ github.event.inputs.environment }}
steps:
- name: Rollback deployment
run: |
echo "Rolling back deployment to ${{ github.event.inputs.environment }}"
echo "Rollback completed"
+197
View File
@@ -0,0 +1,197 @@
name: Issue Triage
on:
issues:
types: [opened, edited]
permissions:
contents: read
issues: write
jobs:
triage:
name: Deterministic issue triage
runs-on: ubuntu-latest
steps:
- name: Apply labels and publish triage card
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.issue;
const issueNumber = issue.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
const text = `${issue.title}\n${issue.body || ""}`.toLowerCase();
const statusLabels = new Set([
"status:needs-triage",
"status:needs-info",
"status:repro-ready",
"status:confirmed",
"status:in-progress",
"status:blocked",
"status:ready-to-merge",
"status:done",
]);
const nextLabels = new Set();
const reasons = [];
// Type classification
if (/(security|vulnerability|cve|hardening|auth bypass|cors)/.test(text)) {
nextLabels.add("type:security");
reasons.push("Detected security-oriented keywords.");
} else if (/(question|how do i|help|clarify)/.test(text)) {
nextLabels.add("type:question");
reasons.push("Detected question/support language.");
} else if (/(docs|documentation|readme|guide)/.test(text)) {
nextLabels.add("type:docs");
reasons.push("Detected documentation-related language.");
} else if (/(feature|enhancement|improve|request)/.test(text)) {
nextLabels.add("type:enhancement");
reasons.push("Detected enhancement/request language.");
} else {
nextLabels.add("type:bug");
reasons.push("Defaulted to bug classification.");
}
// Area classification
if (/(sirius_api_key|x-api-key|401|auth|nextauth|jwt|session)/.test(text)) {
nextLabels.add("area:auth");
reasons.push("Matched auth/API-key indicators.");
}
if (/(installer|startup|secret|nextauth_secret|initial_admin_password|postgres_password)/.test(text)) {
nextLabels.add("area:installer-secrets");
reasons.push("Matched installer/startup secret indicators.");
}
if (/(docker-compose\.dev|dev overlay|volume mount|mount shadow|prisma)/.test(text)) {
nextLabels.add("area:compose-dev");
reasons.push("Matched dev-overlay/compose indicators.");
}
if (/(docker-compose\.prod|production overlay|hardened production)/.test(text)) {
nextLabels.add("area:compose-prod");
reasons.push("Matched production overlay indicators.");
}
if (/(ui|frontend|next\.js|trpc|browser)/.test(text)) nextLabels.add("area:ui");
if (/(api|fiber|endpoint|rest)/.test(text)) nextLabels.add("area:api");
if (/(engine|scanner|grpc|agent)/.test(text)) nextLabels.add("area:engine");
if (/(rabbitmq|queue|amqp)/.test(text)) nextLabels.add("area:rabbitmq");
if (/(postgres|database|migration|prisma schema)/.test(text)) nextLabels.add("area:postgres");
if (/(valkey|redis|cache)/.test(text)) nextLabels.add("area:valkey");
if (/(windows|wsl|crlf)/.test(text)) nextLabels.add("platform:windows");
// Severity hint
if (/(critical|auth bypass|remote code execution|data loss|privilege escalation)/.test(text)) {
nextLabels.add("sev:critical");
} else if (/(stack won't boot|cannot start|service down|outage|unusable|401 everywhere)/.test(text)) {
nextLabels.add("sev:high");
} else if (/(intermittent|major|fails often)/.test(text)) {
nextLabels.add("sev:medium");
} else {
nextLabels.add("sev:low");
}
// Missing info checks for fast mobile triage
const missing = [];
if (!/(repro|steps to reproduce|reproduction)/.test(text)) {
missing.push("Reproduction steps");
}
if (!/(docker compose logs|logs --no-color|stack trace|error:)/.test(text)) {
missing.push("Relevant service logs");
}
if (!/(docker compose config --quiet|installer|sirius-installer)/.test(text)) {
missing.push("Installer/config-render validation evidence");
}
if (missing.length > 0) {
nextLabels.add("status:needs-info");
reasons.push("Missing diagnostics were detected.");
} else {
nextLabels.add("status:repro-ready");
reasons.push("Sufficient diagnostics detected for reproduction.");
}
// Remove existing status labels to keep lifecycle single-valued
for (const label of issue.labels.map((l) => l.name)) {
if (statusLabels.has(label) && !nextLabels.has(label)) {
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: issueNumber,
name: label,
});
} catch (error) {
core.warning(`Could not remove label ${label}: ${error.message}`);
}
}
}
// Add computed labels
const labelsToAdd = [...nextLabels];
if (labelsToAdd.length > 0) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: issueNumber,
labels: labelsToAdd,
});
}
const triageMarker = "<!-- sirius-triage-card -->";
const missingBlock = missing.length
? missing.map((m) => `- [ ] ${m}`).join("\n")
: "- [x] Issue includes baseline diagnostics.";
const body = `${triageMarker}
## Triage Card
**Summary**
- Type: ${[...nextLabels].find((l) => l.startsWith("type:")) || "not-set"}
- Areas: ${[...nextLabels].filter((l) => l.startsWith("area:") || l.startsWith("platform:")).join(", ") || "not-set"}
- Severity hint: ${[...nextLabels].find((l) => l.startsWith("sev:")) || "not-set"}
- Status: ${[...nextLabels].find((l) => l.startsWith("status:")) || "not-set"}
**Why this classification**
${reasons.map((r) => `- ${r}`).join("\n")}
**Missing info checklist**
${missingBlock}
**Relevant runbooks**
- API Key Operations: \`documentation/dev/operations/README.api-key-operations.md\`
- Startup/Secrets ADR: \`documentation/dev/architecture/ADR.startup-secrets-model.md\`
- Auth Surface Matrix: \`documentation/dev/architecture/README.auth-surface-matrix.md\`
**Maintainer mobile commands**
- \`/triage needs-info\`
- \`/triage repro-ready\`
- \`/triage confirmed\`
- \`/test health\`
- \`/test integration\`
- \`/test security auth-surface\`
`;
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: issueNumber,
per_page: 100,
});
const existing = comments.find((c) => c.body && c.body.includes(triageMarker));
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number: issueNumber,
body,
});
}
+19
View File
@@ -0,0 +1,19 @@
name: PR Labeler
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
jobs:
label:
name: Apply path-based labels
runs-on: ubuntu-latest
steps:
- name: Label PR by changed files
uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+123
View File
@@ -0,0 +1,123 @@
name: PR Review Card
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
review-card:
name: Publish review card
runs-on: ubuntu-latest
steps:
- name: Build and post review card
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const pull_number = context.payload.pull_request.number;
const marker = "<!-- sirius-pr-review-card -->";
const files = await github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number,
per_page: 100,
});
const paths = files.map((f) => f.filename);
const changed = new Set();
const risks = [];
const requiredTests = new Set();
const has = (pattern) => paths.some((p) => pattern.test(p));
if (has(/^sirius-ui\//)) {
changed.add("area:ui");
requiredTests.add("Frontend checklist (visual + functional + container checks)");
}
if (has(/^sirius-api\//)) {
changed.add("area:api");
requiredTests.add("Backend API checklist (endpoint, validation, auth checks)");
}
if (has(/^sirius-engine\//)) {
changed.add("area:engine");
requiredTests.add("Docker/container + integration checklist");
}
if (has(/^documentation\//) || has(/^README\.md$/)) {
changed.add("type:docs");
requiredTests.add("Documentation checklist (`lint-docs`, `lint-index`)");
}
if (has(/docker-compose|Dockerfile|\.github\/workflows/)) {
changed.add("area:compose-prod");
requiredTests.add("Container/Docker checklist (`test-build`, `test-health`, `test-integration`)");
risks.push("Runtime/startup contract changed (compose/workflow/dockerfile touched).");
}
if (has(/auth|apikey|nextauth|README\.auth-surface-matrix\.md|README\.api-key-operations\.md/i)) {
changed.add("area:auth");
requiredTests.add("Authentication checklist + `security auth-surface` suite");
risks.push("Auth surface touched; require explicit auth regression evidence.");
}
if (has(/prisma|migration|sirius-postgres/i)) {
changed.add("area:postgres");
requiredTests.add("Database schema/migration checklist");
risks.push("Persistence layer changed; validate migrations and rollback safety.");
}
if (has(/rabbitmq|queue|amqp/i)) {
changed.add("area:rabbitmq");
requiredTests.add("Integration + queue behavior validation");
}
if (risks.length === 0) {
risks.push("No high-risk patterns detected by automation.");
}
const body = `${marker}
## PR Review Card
**Changed surfaces**
${[...changed].length ? [...changed].map((c) => `- ${c}`).join("\n") : "- none detected"}
**Risk flags**
${risks.map((r) => `- ${r}`).join("\n")}
**Required testing evidence**
${[...requiredTests].length ? [...requiredTests].map((t) => `- [ ] ${t}`).join("\n") : "- [ ] General smoke + health evidence"}
**Reference checklist**
- \`documentation/dev/test/CHECKLIST.testing-by-type.md\`
**Maintainer commands**
- \`/test health\`
- \`/test integration\`
- \`/test security auth-surface\`
`;
const comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: pull_number,
per_page: 100,
});
const existing = comments.find((c) => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number: pull_number,
body,
});
}
+28
View File
@@ -0,0 +1,28 @@
name: PR Size Labeler
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
permissions:
contents: read
pull-requests: write
jobs:
size:
name: Apply size label
runs-on: ubuntu-latest
steps:
- name: Apply PR size label
uses: pascalgn/size-label-action@v0.5.5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
XS_MAX_SIZE: "25"
S_MAX_SIZE: "99"
M_MAX_SIZE: "299"
L_MAX_SIZE: "699"
XL_MAX_SIZE: "1499"
FAIL_IF_XL: "false"
IGNORE_FILE_PATTERNS: |
*.lock
*.snap
@@ -0,0 +1,150 @@
name: Publish Release Image Tags
on:
workflow_dispatch:
inputs:
source_tag:
description: "Existing source image tag (e.g. latest)"
required: true
default: "latest"
target_tag:
description: "Release image tag to publish (e.g. v1.0.0)"
required: true
default: "v1.0.0"
env:
GHCR_OWNER: SiriusScan
REGISTRY: ghcr.io
IMAGE_NAMESPACE: siriusscan
jobs:
retag-and-publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.GHCR_PUSH_USER }}
password: ${{ secrets.GHCR_PUSH_TOKEN }}
- name: Verify source manifests exist for all components
run: |
set -euo pipefail
verify_source_manifest() {
local component="$1"
local source_ref="${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${component}:${{ github.event.inputs.source_tag }}"
echo "Checking source manifest: ${source_ref}"
docker buildx imagetools inspect "${source_ref}" > /dev/null
}
verify_source_manifest sirius-ui
verify_source_manifest sirius-api
verify_source_manifest sirius-engine
verify_source_manifest sirius-postgres
verify_source_manifest sirius-rabbitmq
verify_source_manifest sirius-valkey
- name: Publish sirius-ui release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-ui:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-ui:${{ github.event.inputs.source_tag }}"
- name: Publish sirius-api release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-api:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-api:${{ github.event.inputs.source_tag }}"
- name: Publish sirius-engine release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-engine:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-engine:${{ github.event.inputs.source_tag }}"
- name: Publish sirius-postgres release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-postgres:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-postgres:${{ github.event.inputs.source_tag }}"
- name: Publish sirius-rabbitmq release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-rabbitmq:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-rabbitmq:${{ github.event.inputs.source_tag }}"
- name: Publish sirius-valkey release tag
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-valkey:${{ github.event.inputs.target_tag }}" \
"${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-valkey:${{ github.event.inputs.source_tag }}"
- name: Verify published manifests
run: |
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-ui:${{ github.event.inputs.target_tag }}" > /dev/null
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-api:${{ github.event.inputs.target_tag }}" > /dev/null
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-engine:${{ github.event.inputs.target_tag }}" > /dev/null
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-postgres:${{ github.event.inputs.target_tag }}" > /dev/null
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-rabbitmq:${{ github.event.inputs.target_tag }}" > /dev/null
docker manifest inspect "${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/sirius-valkey:${{ github.event.inputs.target_tag }}" > /dev/null
echo "Published release image tags: ${{ github.event.inputs.target_tag }}"
- name: Verify source and release digest parity
run: |
set -euo pipefail
verify_digest() {
local component="$1"
local source_ref="${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${component}:${{ github.event.inputs.source_tag }}"
local target_ref="${{ env.REGISTRY }}/${{ env.IMAGE_NAMESPACE }}/${component}:${{ github.event.inputs.target_tag }}"
local source_digest
local target_digest
# Human-readable output no longer has a stable "^Digest:" line; use JSON index digest.
source_digest=$(docker buildx imagetools inspect "$source_ref" --format '{{json .}}' | jq -r '.manifest.digest')
target_digest=$(docker buildx imagetools inspect "$target_ref" --format '{{json .}}' | jq -r '.manifest.digest')
echo "${component} source digest: ${source_digest}"
echo "${component} target digest: ${target_digest}"
if [ -z "$source_digest" ] || [ -z "$target_digest" ] || [ "$source_digest" != "$target_digest" ]; then
echo "Digest verification failed for ${component}" >&2
exit 1
fi
}
verify_digest sirius-ui
verify_digest sirius-api
verify_digest sirius-engine
verify_digest sirius-postgres
verify_digest sirius-rabbitmq
verify_digest sirius-valkey
- name: Verify anonymous access for release tag
run: |
bash scripts/verify-ghcr-public-access.sh "${{ github.event.inputs.target_tag }}"
validate-public-release-stack:
needs: retag-and-publish
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Smoke-test published public compose path
run: |
bash scripts/validate-public-compose-path.sh "${{ github.event.inputs.target_tag }}"
@@ -0,0 +1,65 @@
name: Slash Command Dispatch
on:
issue_comment:
types: [created]
permissions:
contents: write
issues: read
pull-requests: read
jobs:
dispatch:
name: Dispatch chatops command
runs-on: ubuntu-latest
if: >
github.event.issue.pull_request || !github.event.issue.pull_request
steps:
- name: Validate and dispatch
uses: actions/github-script@v7
with:
script: |
const commentBody = (context.payload.comment.body || "").trim();
const assoc = context.payload.comment.author_association || "";
const allowedAssociations = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
if (!commentBody.startsWith("/")) {
core.info("Not a slash command, skipping.");
return;
}
if (!allowedAssociations.has(assoc)) {
core.info(`Ignoring slash command from association: ${assoc}`);
return;
}
const isSupported =
commentBody.startsWith("/triage ") ||
commentBody === "/triage" ||
commentBody.startsWith("/test ");
if (!isSupported) {
core.info(`Unsupported slash command: ${commentBody}`);
return;
}
const issueNumber = context.payload.issue.number;
const isPr = !!context.payload.issue.pull_request;
const prNumber = isPr ? issueNumber : null;
await github.request("POST /repos/{owner}/{repo}/dispatches", {
owner: context.repo.owner,
repo: context.repo.repo,
event_type: "chatops-command",
client_payload: {
command: commentBody,
issue_number: issueNumber,
pr_number: prNumber,
is_pr: isPr,
comment_id: context.payload.comment.id,
actor: context.actor,
},
});
core.info(`Dispatched chatops command: ${commentBody}`);
+43
View File
@@ -0,0 +1,43 @@
name: Stale Issue and PR Hygiene
on:
schedule:
- cron: "30 4 * * *"
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
stale:
name: Mark stale issues and PRs
runs-on: ubuntu-latest
steps:
- name: Process stale issues and PRs
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
This issue has had no activity for 60 days and is now marked stale.
If this is still relevant, add an update and we will keep it open.
close-issue-message: >
Closing this issue due to inactivity.
Comment with updated context to reopen if work is still needed.
stale-pr-message: >
This pull request has had no activity for 60 days and is now marked stale.
Please push updates or comment if it should remain open.
close-pr-message: >
Closing this pull request due to inactivity.
Reopen or open a new PR when updates are ready.
days-before-issue-stale: 60
days-before-issue-close: 14
days-before-pr-stale: 60
days-before-pr-close: 14
exempt-issue-labels: "type:security,sev:critical,status:blocked"
exempt-pr-labels: "type:security,sev:critical,status:blocked"
exempt-all-milestones: true
stale-issue-label: "status:needs-info"
stale-pr-label: "status:needs-info"
close-issue-label: "status:done"
close-pr-label: "status:done"
@@ -0,0 +1,93 @@
name: Validate Docker Configuration
on:
pull_request:
paths:
- "docker-compose*.yaml"
- ".github/workflows/validate-docker-config.yml"
push:
branches: [main, develop]
paths:
- "docker-compose*.yaml"
- ".github/workflows/validate-docker-config.yml"
jobs:
validate-docker-config:
name: Validate Docker Compose Configuration
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate docker-compose.override.yaml
run: |
echo "🔍 Validating docker-compose.override.yaml configuration..."
# Check if volume mounts in sirius-engine are commented out
if grep -E "^\s*-\s+\.\./minor-projects/" docker-compose.override.yaml; then
echo "❌ FAIL: Volume mounts are uncommented in docker-compose.override.yaml"
echo "Found uncommented volume mounts:"
grep -E "^\s*-\s+\.\./minor-projects/" docker-compose.override.yaml
echo ""
echo "💡 These should be commented out with '#' to prevent accidental commits"
echo "💡 Use docker-compose.local.yaml for local development overrides"
exit 1
fi
# Check that the commented examples exist
if ! grep -E "^\s*#\s*-\s+\.\./minor-projects/" docker-compose.override.yaml; then
echo "⚠️ WARNING: No commented volume mount examples found"
echo "💡 Consider adding commented examples for developer reference"
fi
echo "✅ docker-compose.override.yaml validation passed"
- name: Validate no local files committed
run: |
echo "🔍 Checking for accidentally committed local files..."
# Check if any local override files were committed
if [ -f "docker-compose.local.yaml" ]; then
echo "❌ FAIL: docker-compose.local.yaml should not be committed"
echo "💡 This file is for local development only and should be git-ignored"
exit 1
fi
# Check for any other local override patterns
if ls docker-compose.*.local.yaml 2>/dev/null; then
echo "❌ FAIL: Local docker-compose files found:"
ls docker-compose.*.local.yaml
echo "💡 These files should be git-ignored"
exit 1
fi
echo "✅ No local override files found in repository"
- name: Validate no outdated template files
run: |
echo "🔍 Checking for outdated template files..."
# Check for old template files that should not exist
if [ -f "docker-compose.local.example.yaml" ]; then
echo "❌ FAIL: docker-compose.local.example.yaml is an outdated template"
echo "💡 This file is from an old implementation and should be removed"
exit 1
fi
echo "✅ No outdated template files found"
- name: Summary
if: success()
run: |
echo "🎉 All Docker configuration validations passed!"
echo ""
echo "📋 What was validated:"
echo " ✅ Volume mounts are properly commented in docker-compose.override.yaml"
echo " ✅ No local override files accidentally committed"
echo " ✅ No outdated template files found"
echo ""
echo "💡 For local development, developers should:"
echo " 1. Run './scripts/dev-setup.sh init' to create local overrides"
echo " 2. Edit docker-compose.local.yaml (git-ignored) for their needs"
echo " 3. Use './scripts/dev-setup.sh start-extended' for extended development"
@@ -0,0 +1,56 @@
# Verifies that the GitHub Release tag has matching, anonymously pullable images
# for all six GHCR packages used by docker-compose.yaml. Complements ci.yml, which
# only validates the public compose path for `latest` on main pushes.
name: Verify GHCR Release Tag
on:
release:
types: [published]
workflow_dispatch:
inputs:
image_tag:
description: "Image tag to verify (e.g. v1.0.0). Leave empty to resolve the latest GitHub release tag."
required: false
default: ""
schedule:
# Weekly: catch drift between GitHub Releases and GHCR semver tags
- cron: "0 12 * * 1"
permissions:
contents: read
jobs:
verify-anonymous-ghcr:
name: Anonymous GHCR manifest check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Resolve image tag
id: tag
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
MANUAL="${{ inputs.image_tag }}"
if [ -n "${MANUAL}" ]; then
echo "tag=${MANUAL}" >> "$GITHUB_OUTPUT"
echo "Resolved tag (manual): ${MANUAL}"
exit 0
fi
fi
if [ "${{ github.event_name }}" = "release" ]; then
TAG="${{ github.event.release.tag_name }}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "Resolved tag (release event): ${TAG}"
exit 0
fi
TAG=$(gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq '.tag_name')
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "Resolved tag (latest GitHub release): ${TAG}"
- name: Verify anonymous GHCR access (compose-rendered refs)
run: |
bash scripts/verify-ghcr-public-access.sh "${{ steps.tag.outputs.tag }}"
+29
View File
@@ -0,0 +1,29 @@
name: Welcome First-Time Contributors
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
permissions:
issues: write
pull-requests: write
jobs:
welcome:
name: Welcome contributors
runs-on: ubuntu-latest
steps:
- name: Post welcome message
uses: actions/first-interaction@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: |
Thanks for opening your first issue in Sirius Scan.
Please include as much diagnostic detail as possible so maintainers can triage quickly.
You can also use Discussions for questions and design proposals.
pr-message: |
Thanks for your first pull request to Sirius Scan.
Please complete the PR template checklist and include validation evidence.
A maintainer will review as soon as possible.