diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..e7f9c8f3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,35 @@ +name: Bug Report +description: Report a defect in SkillHub +title: "[Bug] " +labels: + - bug +body: + - type: textarea + id: summary + attributes: + label: Summary + description: What happened? + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps To Reproduce + description: Include commands, requests, or UI flow + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behavior + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: Branch, commit, runtime profile, browser, OS, etc. + - type: textarea + id: logs + attributes: + label: Logs Or Screenshots diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..b40231a6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Security Report + url: https://example.invalid/security-contact + about: Do not file public issues for suspected vulnerabilities. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..0cbacbfd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,28 @@ +name: Feature Request +description: Propose a new capability or workflow improvement +title: "[Feature] " +labels: + - enhancement +body: + - type: textarea + id: problem + attributes: + label: Problem + description: What user or operator problem does this solve? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed Solution + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + - type: textarea + id: impact + attributes: + label: Impact + description: Auth, API, migration, deployment, observability, or UX impact diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..a74bf0af --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,27 @@ +## Summary + +- What changed? +- Why is this needed? + +## Validation + +- [ ] Backend tests passed +- [ ] Frontend typecheck/build passed +- [ ] Smoke test run when relevant + +Commands run: + +```bash +# paste commands here +``` + +## Risk + +- User-facing impact: +- Deployment or migration impact: +- Rollback approach: + +## Notes + +- Related issue: +- Follow-up work: diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..90643adc --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,33 @@ +# Code of Conduct + +## Our Standard + +Contributors and maintainers are expected to keep discussion technical, +respectful, and constructive. + +Examples of expected behavior: + +- Focus on the problem, tradeoffs, and evidence. +- Assume good intent, but challenge weak reasoning directly. +- Share actionable feedback. +- Respect different levels of experience and domain knowledge. + +Examples of unacceptable behavior: + +- Harassment, insults, or personal attacks +- Bad-faith argumentation or repeated hostility +- Publishing private or sensitive information without permission +- Disruptive behavior that blocks productive collaboration + +## Enforcement + +Project maintainers may remove comments, reject contributions, or restrict +participation for behavior that violates this code of conduct. + +Serious or repeated violations may result in a temporary or permanent ban from +project spaces. + +## Reporting + +Report conduct issues privately to the maintainers through an internal contact +channel. Do not use public issues for personal or sensitive reports. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..99f87e14 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,75 @@ +# Contributing to SkillHub + +## Scope + +SkillHub is a self-hosted registry for agent skills. Contributions should +preserve the existing architecture and product direction documented in +[`docs/`](./docs). + +## Before You Start + +- Read [`README.md`](./README.md) for local development commands. +- Check the relevant design docs before changing behavior. +- Open an issue for non-trivial changes before sending a large pull request. + +## Development Setup + +Prerequisites: + +- Docker and Docker Compose +- Java 21 +- Node.js and `pnpm` + +Start the local stack: + +```bash +make dev-all +``` + +Useful commands: + +```bash +make test +make typecheck-web +make build-web +./scripts/smoke-test.sh +``` + +Stop the stack: + +```bash +make dev-all-down +``` + +## Change Guidelines + +- Keep changes focused. Avoid mixing refactors with behavior changes. +- Follow existing module boundaries across `server/`, `web/`, and `docs/`. +- Add or update tests when behavior changes. +- Update docs when APIs, auth flows, deployment, or operator workflows change. +- Prefer backward-compatible changes unless the issue explicitly allows a break. + +## Pull Requests + +Before opening a pull request, make sure: + +- The branch is rebased or merged cleanly from the target branch. +- Relevant backend tests pass. +- Frontend typecheck/build passes when frontend files changed. +- Smoke coverage is updated when operator-facing workflows change. +- The pull request description explains motivation, scope, and rollout impact. + +## Commit Style + +Conventional-style subjects are preferred, for example: + +- `feat(auth): add local account login` +- `fix(ops): align smoke test with csrf flow` +- `docs(deploy): clarify runtime image usage` + +## Reporting Security Issues + +Do not open public issues for suspected security vulnerabilities. + +Report them privately to the maintainers through your internal security process +or a private maintainer contact channel. diff --git a/README.md b/README.md index a4ed20c5..3cba27ee 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ firewall, with the same polish you'd expect from a public registry. ## Quick Start +Start the full local stack with: `curl -fsSL https://raw.githubusercontent.com/iflytek/skillhub/main/scripts/runtime.sh | sh -s -- up` + ### Prerequisites - Docker & Docker Compose @@ -149,6 +151,9 @@ private, run `docker login ghcr.io` before `docker compose up -d`. Contributions are welcome. Please open an issue first to discuss what you'd like to change. +- Contribution guide: [`CONTRIBUTING.md`](./CONTRIBUTING.md) +- Code of conduct: [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) + ## License MIT diff --git a/scripts/runtime.sh b/scripts/runtime.sh new file mode 100644 index 00000000..1d04b4d5 --- /dev/null +++ b/scripts/runtime.sh @@ -0,0 +1,174 @@ +#!/bin/sh + +set -eu + +COMMAND="up" +if [ "$#" -gt 0 ] && [ "${1#-}" = "$1" ]; then + COMMAND="$1" + shift +fi + +SKILLHUB_REF="${SKILLHUB_REF:-main}" +SKILLHUB_HOME_DEFAULT="${TMPDIR:-/tmp}/skillhub-runtime" +SKILLHUB_HOME="${SKILLHUB_HOME:-$SKILLHUB_HOME_DEFAULT}" +SKILLHUB_VERSION_VALUE="${SKILLHUB_VERSION:-}" +SKILLHUB_SERVER_IMAGE_VALUE="${SKILLHUB_SERVER_IMAGE:-}" +SKILLHUB_WEB_IMAGE_VALUE="${SKILLHUB_WEB_IMAGE:-}" + +while [ "$#" -gt 0 ]; do + case "$1" in + --version) + [ "$#" -ge 2 ] || { echo "Missing value for --version" >&2; exit 1; } + SKILLHUB_VERSION_VALUE="$2" + shift 2 + ;; + --home) + [ "$#" -ge 2 ] || { echo "Missing value for --home" >&2; exit 1; } + SKILLHUB_HOME="$2" + shift 2 + ;; + --ref) + [ "$#" -ge 2 ] || { echo "Missing value for --ref" >&2; exit 1; } + SKILLHUB_REF="$2" + shift 2 + ;; + --server-image) + [ "$#" -ge 2 ] || { echo "Missing value for --server-image" >&2; exit 1; } + SKILLHUB_SERVER_IMAGE_VALUE="$2" + shift 2 + ;; + --web-image) + [ "$#" -ge 2 ] || { echo "Missing value for --web-image" >&2; exit 1; } + SKILLHUB_WEB_IMAGE_VALUE="$2" + shift 2 + ;; + --help|-h) + cat < Use a specific image tag, for example v0.1.0 + --home Store runtime files in a specific directory + --ref Download runtime files from a specific Git ref + --server-image Override backend image repository + --web-image Override frontend image repository +EOF + exit 0 + ;; + *) + echo "Unsupported argument: $1" >&2 + exit 1 + ;; + esac +done + +SKILLHUB_RAW_BASE="${SKILLHUB_RAW_BASE:-https://raw.githubusercontent.com/iflytek/skillhub/$SKILLHUB_REF}" +COMPOSE_FILE="$SKILLHUB_HOME/compose.release.yml" +ENV_EXAMPLE_FILE="$SKILLHUB_HOME/.env.release.example" +ENV_FILE="$SKILLHUB_HOME/.env.release" + +find_compose() { + if docker compose version >/dev/null 2>&1; then + echo "docker compose" + return 0 + fi + + if command -v docker-compose >/dev/null 2>&1; then + echo "docker-compose" + return 0 + fi + + echo "Docker Compose is required." >&2 + exit 1 +} + +download_file() { + src="$1" + dest="$2" + tmp="$dest.tmp" + curl -fsSL "$src" -o "$tmp" + mv "$tmp" "$dest" +} + +set_env_value() { + key="$1" + value="$2" + + if [ ! -f "$ENV_FILE" ]; then + return 0 + fi + + tmp="$ENV_FILE.tmp" + if grep -q "^$key=" "$ENV_FILE"; then + sed "s|^$key=.*|$key=$value|" "$ENV_FILE" >"$tmp" + else + cat "$ENV_FILE" >"$tmp" + printf '%s=%s\n' "$key" "$value" >>"$tmp" + fi + mv "$tmp" "$ENV_FILE" +} + +prepare_runtime_files() { + mkdir -p "$SKILLHUB_HOME" + download_file "$SKILLHUB_RAW_BASE/compose.release.yml" "$COMPOSE_FILE" + download_file "$SKILLHUB_RAW_BASE/.env.release.example" "$ENV_EXAMPLE_FILE" + + if [ ! -f "$ENV_FILE" ]; then + cp "$ENV_EXAMPLE_FILE" "$ENV_FILE" + fi + + if [ -n "$SKILLHUB_VERSION_VALUE" ]; then + set_env_value "SKILLHUB_VERSION" "$SKILLHUB_VERSION_VALUE" + fi + + if [ -n "$SKILLHUB_SERVER_IMAGE_VALUE" ]; then + set_env_value "SKILLHUB_SERVER_IMAGE" "$SKILLHUB_SERVER_IMAGE_VALUE" + fi + + if [ -n "$SKILLHUB_WEB_IMAGE_VALUE" ]; then + set_env_value "SKILLHUB_WEB_IMAGE" "$SKILLHUB_WEB_IMAGE_VALUE" + fi +} + +run_compose() { + compose_cmd="$(find_compose)" + # shellcheck disable=SC2086 + $compose_cmd --env-file "$ENV_FILE" -f "$COMPOSE_FILE" "$@" +} + +prepare_runtime_files + +case "$COMMAND" in + up) + run_compose up -d + cat <&2 + echo "Usage: sh runtime.sh [up|down|clean|ps|logs|pull] [options]" >&2 + exit 1 + ;; +esac