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
7 changes: 5 additions & 2 deletions template/.github/ISSUE_TEMPLATE/config.yml.jinja
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Report a security vulnerability
url: https://github.com/{{ github_username }}/{{ project_slug }}/security/advisories/new
about: Report security vulnerabilities privately. Do not open a public issue.
- name: Question or Discussion
url: https://github.com/{{ github_username }}/{{ package_name }}/discussions
url: https://github.com/{{ github_username }}/{{ project_slug }}/discussions
about: Please use GitHub Discussions for questions and general discussions
- name: Documentation
url: https://{{ github_username }}.github.io/{{ package_name }}/
url: https://{{ project_slug }}.readthedocs.io/
about: Check the documentation for guides and API references
16 changes: 16 additions & 0 deletions tests/test_security_hardening.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,22 @@ def test_governance_files_ship_for_every_repo(copie):
assert not (result.project_dir / "CODEOWNERS").exists()


def test_issue_chooser_offers_private_vulnerability_reporting(copie):
"""The issue chooser links the private advisory form that SECURITY.md points to.

Without it, a reporter who goes straight to "New issue" never sees the private
channel and files the vulnerability publicly. The link must use the repository
slug, as SECURITY.md does, not the package name.
"""
result = copie.copy()
config = _read(result.project_dir, ".github/ISSUE_TEMPLATE/config.yml")
url = "https://github.com/testuser/test-project/security/advisories/new"
assert url in config, "issue chooser does not link private vulnerability reporting"
assert url in _read(result.project_dir, "SECURITY.md"), "issue chooser and SECURITY.md disagree"
# Listed first, ahead of Discussions, so it is the first option a reporter sees.
assert config.index(url) < config.index("/discussions")


def test_publish_flow_is_self_contained_with_sbom(copie):
"""The publish path builds and publishes in one run, with no third-party broker, plus an SBOM."""
result = copie.copy(extra_answers={"include_actions": True})
Expand Down
14 changes: 14 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,20 @@ def test_github_actions_when_enabled(copie):
assert (result.project_dir / ".git-cliff.toml").is_file(), ".git-cliff.toml not created"


def test_issue_chooser_links_use_the_repository_slug(copie):
"""The issue chooser links the repository and docs site by slug, as every other link does.

The package name differs from the slug whenever the project name has a separator
(``test_project`` against ``test-project``), and a link built from it points at a
repository and docs site that do not exist.
"""
result = copie.copy()
config = (result.project_dir / ".github" / "ISSUE_TEMPLATE" / "config.yml").read_text(encoding="utf-8")
assert "https://github.com/testuser/test-project/discussions" in config
assert "https://test-project.readthedocs.io/" in config
assert "test_project" not in config, "issue chooser links the package name instead of the repository slug"


def test_renovate_config_self_contained_by_default(copie):
"""With no preset, renovate.json is a full self-contained, valid config.

Expand Down
Loading