The format is based on Keep a Changelog. The project uses semantic versioning (see semver).
- New
SingleFileEditor
, derived fromPatchDriver
, for editing single files.- Parameter
target_file
, will be fed its text content toprocess_file()
. - Use via
from mass_driver.drivers.bricks import SingleFileEditor
.
- Parameter
- New
GlobFileEditor
, similarly for editing multiple files from glob pattern.- Use via
from mass_driver.drivers.bricks import GlobFileEditor
.
- Use via
- Update
pyGithub
to2.1.1
, now throttles Github API to avoid ratelimits
- Catch and log import errors during activity loading, previously silent crashes
- Completing an activity (source, migration, forge) now summarizes results
- Breakdown of repo count per outcome type, then sorted list of repos per type
- FASTER: Optional, experimental multi-threaded per-repo processsing!
Handling of clone, scan, patching is done as individual thread per repo, with
N=8 pooled threads.
- Early data shows a x6 improvement in performance, as cloning one repo doesn't block others anymore.
- Enable via new experimental flag
run --parallel
, defaulting toFalse
- BREAKING: Renamed
Repo
toSourcedRepo
inmass_driver.models.repository
- This exposes better the idea of "a Repo as it was Source-d", in contrast to
ClonedRepo
"a Repo after it was cloned". - Also avoids clashes with
git.Repo
object from gitpython dependency.
- This exposes better the idea of "a Repo as it was Source-d", in contrast to
- Replaced all
print()
calls tologging
module - Loggers used are mostly nested:
- from
root
(default) - to
run
(or other file-activity-based) - to
run.repo.<repo-id>
for logs for a specific repo's processing - to subloggers like
run.repo.<repo-id>.driver.<driver-plugin-name>
- from
PatchDriver
now has alogger
obj for such customized logging: Repo-processing setsPatchdriver.logger
namedrun.repo.<repo-id>.driver.<driver-plugin-name>
- ACTION: Please replace any
print
withself.logger.info
!
- ACTION: Please replace any
- Attempting to run a Forge activity with
git_push_first=True
, without migration or scan activity, no longer causes exit without processing any repos. Clone step invoked properly mean remote-clone URLs are now supported, converted to local filepaths internally. make docs
now works again withsphinx-autodoc2
: Pinnedastroid
dep to2.15.8
(< 3.0.0) to avoid the regression caused by unpinnedastroid
.
ShellDriver
no longer crashes due to irrelevant dataclass import- Updated
pyGithub
, fixes "missing cryptography" error - Error messages for bad config file for Sources no longer insist wrongly about "Forge config error". Now detecting the validation error's model properly.
- Failing to load a scanner that was selected in config now throws
ImportError
on the first plugin-load failure, instead of silently skipping the scanner.
- Updated to python-template v1.3.0 (from 1.1.0)
github-app
forge no longer crashes due to type confusion on a param.
- Formatting of the % of PR per status back to 2 digits precision not 11.
Breaking interface of Forge
to facilitate new view-pr
feature.
- New
view-pr
feature for bulk reviewing the status of PRs that already exist.
- BREAKING: New
Forge.get_pr_status()
, required from derived classes, returning a string status, used as key to group PRs together for summary purposes. - BREAKING: New
Forge.pr_statuses
property, required from derived classes, returning a list of all possible string statuses ofForge.get_pr_status()
, sorted from most complete (e.g. merged) to least complete (e.g. not merged, has merge-conflicts).
- BREAKING: Removed
Forge.get_pr()
, which had unclear return type anyway.
Major break of interface: Rework of the cloning system, merges migration/scan
codepaths, enabling use of Source-discovered information in PatchDriver.run
.
- BREAKING:
PatchDriver.run()
passesClonedRepo
obj, notpathlib.Path
.- Any use of
repo
in yourPatchDriver.run()
should userepo.cloned_path
. - See
ClonedRepo
docs, contains information derived fromSource
, such aspatch_data
field, arbitrary source-issued information dict.
- Any use of
- BREAKING:
tests.fixtures.massdrive()
now returns 3-item-tuple, not 2.- Returned tuple:
PatchResult
,ForgeResult
,ScanResult
(orNone
) - Any tests using
fixtures.massdrive
should now setmig, forge, scan =
... - Swap
fixtures.massdrive_scan
withfixtures.massdrive
accepting 2 junk arg
- Returned tuple:
- BREAKING:
mass-driver scan
CLI removed, now part ofmass-driver run
. Activity flow forrun
command is now:- Source discovery phase (if any, or from CLI), generating
Repo
list - Main phase, iterating over each Repo, first to clone them =
ClonedRepo
list - Inside main phase, scan (if any), generating
ScanResult
- Inside main phase, migrate (if any), generating
MigrationResult
- After main phase, interactively pause for review if requested
- Forge activity, iterating over each repo again, creating
ForgeResult
- Source discovery phase (if any, or from CLI), generating
- BREAKING:
models.source
module renamed tomodels.repository
.
- Scan+Migration+Forge can now ALL happen in one run command:
- Clones one repo, then scanning it, then migrating it, then next repo
- Can thus do all of Source -> [Clone] -> Scan -> Migrate -> Forge
- New
csv-filelist
Source for importing repos in CSV file format - New
tests.fixture.massdrive_runlocal()
func to enable source testing
- Secret tokens for Github plugins no longer leak on config dump
(
--json-outfile
flag), by replacingstr
withpydantic.SecretStr
.- Docs updated to warn downstream devs about this risk.
- Pin
pydantic
to1.*
, as breaking version2.0
was just released.
- New
source
feature for discovering what repos to patch/scan.Source
s are plugins withdiscover()
method, returningRepo
s by ID.- Alternative
sources
subcommand to list and detail them - New TOML file entry
[mass-driver.source]
, with subkeysource_name
used to select which source plugin to enable. - Simple sources provided:
repo-list
for in-activity-file repository listrepo-filelist
to point to a separate file listing repostemplate-filelist
to expand a template against a file listing repos
github-search
andgithub-app-search
Sources for Github Repository search- CLI args
--repo-path
and--repo-filelist
still available, overriding any source, so thatmassdriver.source
is only required if lacking CLI args
- CI (pytest, pre-commit) set up via Github Actions: PR #1
- New
file_ownership
parameter forstamper
, defaulting to0664
.
- Exit codes harmonized:
0
for success1
for failures during the main function2
for argument parsing errors
stamper
driver now creates any missing parent folder to the target- Remove test depending on
git clone
from Github: Faster, offline tests now
scan
command now uses--json-outfile
as expected
- New
scan
feature for scanning repos with arbitrary python functions. See new "Scanning" docs:- Scanners are plugins declared under
mass-driver.scanners
, linking to functions likemy_scanner(repo: Path) -> dict[str, Any]
- Alternative
scanners
command to list out detected, available scanners - New TOML file entry
[mass-driver.scan]
, with subkeyscanner_names
used to select which scanner plugins to enable. - Simple scanners
root-files
anddockerfile-from
provided for reference - New fixture
massdriver_scan
andmassdriver_scan_check
for testing scanners
- Scanners are plugins declared under
- New optional CLI parameter
--json-outfile
forrun
andscan
, to save the activity outcome to JSON files for analysis
- Test fixture
massdrive_check_file
now returns uncheckedresult
andreference
blobs for equality assertion (assert result == reference
) to be done by the caller. This enables plugins likepytest-clarity
to show colorful diff. Users ofmassdrive_check_file
need to change (on pain of lack of test assertion):
- massdrive_check_file(workdir)
+ result, reference = massdrive_check_file(workdir)
+ assert result == reference, "Massdriver result should match reference"
- Auto-detect repo's base branch for Forge: parameter
base_branch
now optional, defaulting to repo's default branch
- New
github-app
forge plugin for creating PRs on Github when running mass-driver as a Github App - New Forge params:
forge_config
dict, for Forge-specific non-sensitive config to keep in config file, complementing envvars. Similar todriver_config
for Migration.interactive_pause_every
int, for blocking the Forge, pausing for confirmation interactively every few PRs generated. Disabled by default, set to 1 to block every PR, or 5 every 5...
- Unused
migration_name
field of Migration now removed
Forge
subclasses can now grab config via envvars prefixedFORGE_
. Observe thatForge
now derives frompydantic.BaseSettings
, see BaseSettings docs.- New, simpler testing fixture
massdrive_check_file
for PatchDriver that affect single files
- New optional Migration params:
commit_author_name
+commit_author_email
, used to override the git commit author.
- New file type
Activity
combinesMigration
andForge
- New
Forge
nameddummy
for testing purposes - New
git_push_first
boolean param in Forge to disable git pushing. - New
ActivityOutcome
to capture the full result of a migration/forge sequence
- Replace commands
run-migration
+run-forge
by newrun
, using theActivity
file type with optionals. - Internals refactored: all Pydantic objects now under
mass_driver.models
(PatchDriver
,Forge
,Activity
)
- Options
--really-commit-changes
and--dry-run
- New
ROADMAP.md
to clarify The Plan.
- Upgrade minimum Python version to 3.11 to use
tomllib
- Replace
tomlkit
with stdlibtomllib
- Migrations, once loaded from TOML, are now proper dict again
PatchDriver
instance now independent across repos
- Upgrade pre-commit dependencies + poetry in Dockerfile
- Update pyproject.toml for release to Pypi
- Forges now discovered via setuptools
- New "run-forge" subcommand for creating PRs for on-disk branches
- Implemented GithubForge for PR creation on Github
- New "Stamper"
PatchDriver
for "stamping" new files on repos
- Incorrect Repo creation causing silent cloning errors on some devices
- New plugin system for including third-party PatchDrivers, based on the setuptools "entrypoints" system.
- CLI Subcommands for inspecting drivers, running migrations...
- PatchDriver test harness, for ease of plugin development.
- Project objectives (gherkin features in
features/
) now part of docs
PatchDriver
now inherits Pydantic BaseModel (allows serialization)PatchDriver
func prototype:run(repo: Path) -> PatchResult
- Complex PatchDrivers (the ones requiring package dependencies) removed, moved to separate "plugins" repo.
- New
Jsonpatch
Driver, for applying an RFC6902 JSON Patch - New
PreCommit
Driver, for runningpre-commit autoupdate
- New
ShellDriver
for running arbitrary shell commands - New
mass-driver(1)
man page output tomake docs
- PatchDriver API simplified, now using single func for detect + patch:
called via
PatchDriver.run(repo: Path, dry_run: bool)
. - CLI simplified when exposing
PatchDriver.run()
, now uses either--dry-run
(the default setup) or--really-commit-changes
for committing (not pushing)
- Poetry Driver stub for major version of packages in
pyproject.toml
. Showcases JSON Pointers (RFC6901) for structured fields modification.
- Basic clone/detect/patch/commit workflow, with basic Github support
- New python module
mass_driver
, exposed as shell commandmass-driver