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
117 changes: 117 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: CI

on:
push:
branches:
- main
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
tests:
name: Python ${{ matrix.python-version }} / Ubuntu
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "3.14"
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: pyproject.toml

- name: Install project
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Run tests
run: pytest

quality:
name: Lint and package checks
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml

- name: Install development tools
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Run Ruff
run: ruff check .

- name: Validate PyPI README rendering
run: python -m readme_renderer README.md -o /tmp/explain-codebase-readme.html

- name: Build distributions
run: python -m build

- name: Check distributions
run: python -m twine check --strict dist/*

- name: Install wheel in a clean environment
run: |
python -m venv .venv-smoke
.venv-smoke/bin/python -m pip install --upgrade pip
.venv-smoke/bin/python -m pip install dist/*.whl

- name: Smoke-test installed command
run: |
.venv-smoke/bin/explain-codebase --help
.venv-smoke/bin/explain-codebase --version
.venv-smoke/bin/explain-codebase fixtures/python_cli_example --json

windows-smoke:
name: Windows smoke test
runs-on: windows-latest
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml

- name: Install project
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

- name: Run tests
run: pytest

- name: Smoke-test command
run: |
explain-codebase --help
explain-codebase --version
explain-codebase fixtures/python_cli_example --json
75 changes: 75 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Release

on:
push:
tags:
- "v*.*.*"

permissions:
contents: read

jobs:
build:
name: Build distributions
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"
cache: pip
cache-dependency-path: pyproject.toml

- name: Install build tools
run: python -m pip install --upgrade build "readme-renderer[md]>=44" twine

- name: Verify tag matches package version
run: |
python - <<'PY'
import os
import tomllib
from pathlib import Path

package_version = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))["project"]["version"]
tag_version = os.environ["GITHUB_REF_NAME"].removeprefix("v")
if tag_version != package_version:
raise SystemExit(f"Tag {tag_version!r} does not match package version {package_version!r}")
PY

- name: Validate PyPI README rendering
run: python -m readme_renderer README.md -o /tmp/explain-codebase-readme.html

- name: Build wheel and source distribution
run: python -m build

- name: Validate distributions
run: python -m twine check --strict dist/*

- name: Store distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-package-distributions
path: dist/
if-no-files-found: error

publish:
name: Publish to PyPI
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/explain-codebase
permissions:
id-token: write
steps:
- name: Download distributions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-package-distributions
path: dist/

- name: Publish distributions
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
13 changes: 0 additions & 13 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,6 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Abstra
# Abstra is an AI-powered process automation framework.
# Ignore directories containing user credentials, local state, and settings.
# Learn more at https://abstra.io/docs
.abstra/

# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
Expand All @@ -194,13 +188,6 @@ cython_debug/
# PyPI configuration file
.pypirc

# Cursor
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
# refer to https://docs.cursor.com/context/ignore-files
.cursorignore
.cursorindexingignore

# Marimo
marimo/_static/
marimo/_lsp/
Expand Down
81 changes: 81 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.2.0] - 2026-08-02

### Added

- Added support for `.jsx`, `.tsx`, `.mjs`, `.cjs`, `.mts`, and `.cts` source files alongside `.py`, `.js`, and `.ts`.
- Added an installed-version command and cross-version continuous integration checks.
- Added a tag-driven PyPI release workflow with version validation, package checks, artifact handoff, and Trusted Publishing.
- Added complete package metadata, project links, a dedicated changelog, and a security policy.

### Changed

- Hardened local scanning with repository-root containment, symlink rejection, an optional file-count limit, and a 1 MiB per-file limit.
- Limited public GitHub repository preparation to shallow single-branch clones without tags, added a clone timeout, and improved failure handling.
- Improved Python, JavaScript, and TypeScript import resolution across relative paths, package entry files, and supported extension variants.
- Made command-line validation, error handling, output-stream separation, and exit behavior more predictable.
- Expanded package, parser, scanner, remote-target, and command-line tests.
- Refreshed installation, usage, output, and limitation documentation.

### Fixed

- Declared `click` as a direct runtime dependency instead of relying on Typer's transitive dependency.
- Corrected Python package imports, multi-level JavaScript and TypeScript relative imports, async route detection, and project-root selection for file analysis.
- Prevented isolated files from being reported as high-coupling hotspots and rejected non-positive file limits.
- Kept ordinary filesystem-module imports from being reported as side effects until an actual filesystem operation is detected.

### Security

- Disabled repository-configured Git hooks and filesystem monitors, sanitized Git subprocess environments, and bounded Git operations with time limits.
- Pinned third-party workflow actions to immutable commit revisions.
- Rejected source-file links, Windows directory reparse points, paths outside the selected root, and source files larger than 1 MiB.
- Replaced the unbounded JavaScript import pattern with a line-bounded parser.
- Added atomic HTML output, enforced configured node limits for focused graph views, and added a content security policy plus integrity verification for the browser-side graph library.

## [0.1.4] - 2026-03-19

### Changed

- Redesigned the interactive dependency graph for clearer structure and navigation.
- Added architecture, entrypoint, risk, side-effect, and full file-level graph views.
- Updated graph embedding in HTML reports.

## [0.1.3] - 2026-03-17

### Changed

- Refined documentation, examples, and command descriptions.

## [0.1.2] - 2026-03-17

### Added

- Added Git-aware scanning, `.gitignore` filtering, and tracked-file selection.
- Added built-in filtering for common dependency, cache, build, coverage, and environment directories.

## [0.1.1] - 2026-03-17

### Changed

- Updated the package summary and release metadata.

## [0.1.0] - 2026-03-17

### Added

- Published the initial command-line release with repository analysis, dependency graphs, JSON output, HTML reports, onboarding paths, and architecture checks.

[Unreleased]: https://github.com/danyasync/explain-codebase/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/danyasync/explain-codebase/compare/63e1285083b2bdb06de2212aeddcdaebb18e2649...v0.2.0
[0.1.4]: https://pypi.org/project/explain-codebase/0.1.4/
[0.1.3]: https://pypi.org/project/explain-codebase/0.1.3/
[0.1.2]: https://pypi.org/project/explain-codebase/0.1.2/
[0.1.1]: https://pypi.org/project/explain-codebase/0.1.1/
[0.1.0]: https://pypi.org/project/explain-codebase/0.1.0/
Loading