From 1d87ff410784f83294680dc30d1e65d98d56b738 Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Thu, 30 Apr 2026 03:10:43 -0700 Subject: [PATCH 1/6] issues and pull request templates --- .github/ISSUE_TEMPLATE/bug_report.md | 70 +++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 11 +++ .github/ISSUE_TEMPLATE/feature_request.md | 34 +++++++++ .github/ISSUE_TEMPLATE/task.md | 40 +++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 84 +++++++++++++++++++++++ .github/SECURITY.md | 14 ++++ 6 files changed, 253 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/task.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..7ba5b94 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,70 @@ +--- +name: Bug Report +about: Report a reproducible bug to help us improve JSNAPy +title: "[BUG] " +labels: bug +assignees: '' +--- + +## Description +A clear and concise description of the bug. + +## Steps to Reproduce +1. +2. +3. + +## Expected Behavior +What you expected to happen. + +## Actual Behavior +What actually happened. Include any error messages or stack traces. + +``` + +``` + +## Environment + +| Item | Details | +|------------------|---------| +| JSNAPy version (`jsnapy --version`) | | +| Python version | | +| Operating System | | +| Junos OS version | | +| Device model | | +| Install method | pip / source / Docker | + +## Configuration Files + +
+JSNAPy config YAML (redact credentials) + +```yaml + +``` +
+ +
+Test YAML file + +```yaml + +``` +
+ +
+Snapshot XML (if relevant) + +```xml + +``` +
+ +## Additional Context +Add any other context, screenshots, or links to related issues here. + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this is not a duplicate +- [ ] I reproduced the issue on the latest release or `master` branch +- [ ] I have included all relevant config/test files (with credentials redacted) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..37e505e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Report a Security Vulnerability + url: https://github.com/Juniper/jsnapy/security/advisories/new + about: Please report security vulnerabilities privately. Do NOT open a public issue for security bugs. + - name: JSNAPy Wiki & Documentation + url: https://github.com/Juniper/jsnapy/wiki + about: Check the wiki before opening an issue — your question may already be answered. + - name: GitHub Community Support + url: https://github.com/orgs/community/discussions + about: For general GitHub usage questions, ask the community here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..ce7e21f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,34 @@ +--- +name: Feature Request +about: Suggest a new feature or enhancement for JSNAPy +title: "[FEATURE] " +labels: enhancement +assignees: '' +--- + +## Summary +A clear and concise description of the feature you are requesting. + +## Problem / Motivation +Describe the problem this feature would solve, or the use case that motivates the request. +_(e.g. "I find it difficult to ... when ...")_ + +## Proposed Solution +Describe the solution you'd like. Include any new YAML keys, CLI flags, Python API changes, or behaviour you envision. + +```yaml +# Example config / usage snippet (if applicable) +``` + +## Alternatives Considered +List any alternative solutions or workarounds you have already tried or considered, and why they are insufficient. + +## Additional Context +- Links to related issues, PRs, or discussions +- Reference to relevant Junos RPC / operational commands (if applicable) +- Any other context or screenshots + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this is not already requested +- [ ] I checked the [JSNAPy wiki](https://github.com/Juniper/jsnapy/wiki) and this is not already supported +- [ ] I am willing to submit a pull request to implement this feature diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md new file mode 100644 index 0000000..1ef19cd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/task.md @@ -0,0 +1,40 @@ +--- +name: Task +about: Describe a task, chore, or maintenance work to be done in JSNAPy +title: "[TASK] " +labels: task +assignees: '' +--- + +## Summary +A clear and concise description of the task to be completed. + +## Background / Motivation +Explain why this task is needed (e.g. technical debt, CI improvement, dependency upgrade, documentation update). + +## Acceptance Criteria +List the specific conditions that must be met for this task to be considered done. + +- [ ] +- [ ] +- [ ] + +## Implementation Notes +Any technical details, constraints, or approach suggestions relevant to completing the task. + +## Sub-tasks +Break down the work into smaller steps if applicable. + +- [ ] +- [ ] + +## Related Issues / PRs +Link any related issues, pull requests, or discussions. + +## Additional Context +Add any other context, references, or screenshots here. + +## Checklist +- [ ] I searched [existing issues](https://github.com/Juniper/jsnapy/issues) and this task is not already tracked +- [ ] Acceptance criteria are clearly defined above +- [ ] I am willing to submit a pull request for this task diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..171da29 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,84 @@ +## Description + + + +Closes # + +## Type of Change + + + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] Feature / Enhancement (non-breaking change that adds functionality) +- [ ] Task / Chore (refactor, dependency update, CI, docs, etc.) +- [ ] Breaking change (fix or feature that would cause existing functionality to change) + +## Changes Made + + + +- +- +- + +--- + +## Checklist + +### Code Quality + +- [ ] Code follows the project's style guidelines +- [ ] `pylint` reports no new errors or warnings (run against changed files under `lib/jnpr/jsnapy/`) + + ```bash + sudo find ./lib/jnpr/jsnapy -type f -name "*.py" | xargs pylint | grep . + ``` + +- [ ] `black` formatting check passes + + ```bash + black --check --diff --exclude="docs|build|tests|samples|venv" . + ``` + +### Unit Tests + +- [ ] New or updated unit tests have been added under `tests/unit/` +- [ ] All unit tests pass locally + + ```bash + cd tests/unit + nose2 --with-coverage -vvvv + ``` + +- [ ] Code coverage has not decreased + +### Documentation + +- [ ] YAML samples in `samples/` updated or added where applicable +- [ ] `README.md` or wiki references updated (if behaviour changed) + +### General + +- [ ] No hardcoded credentials, IPs, or sensitive data introduced +- [ ] `requirements.txt` / `development.txt` updated (if new packages were added) +- [ ] I have read [CONTRIBUTING.md](../CONTRIBUTING.md) and my contribution complies with the Apache 2.0 License + +--- + +## Testing Matrix + + + +| Python | OS | Pylint | Black | Unit Tests | +|---------|---------------|--------|-------|------------| +| 3.8.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.9.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.10.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.11.x | ubuntu-latest | [ ] | [ ] | [ ] | +| 3.12.x | ubuntu-latest | [ ] | [ ] | [ ] | + +--- + +## Additional Notes + + diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..909999c --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,14 @@ +# Security Policy + +## Supported Versions + +Only the latest stable version of JSNAPy receives security updates. Make sure you are running the most recent release. + +## Reporting a Vulnerability + +Please do not open public issues for security problems. Instead, use GitHub's "Report a vulnerability" feature in the Security tab of this repository. We will review and respond as soon as possible. + +## Security Updates + +If we fix a vulnerability, we will announce it in the release notes. Keep your installation up to date to receive the latest fixes. + From 5710afc71125e718e3ead28c73af37fb87c199ef Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Mon, 4 May 2026 03:57:35 -0700 Subject: [PATCH 2/6] issues and pull request templates --- lib/jnpr/jsnapy/jsnapy.py | 22 +++++++++------------- lib/jnpr/jsnapy/operator.py | 4 ++-- lib/jnpr/jsnapy/sqlite_store.py | 7 ++----- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/lib/jnpr/jsnapy/jsnapy.py b/lib/jnpr/jsnapy/jsnapy.py index 75ee488..fcbebc5 100755 --- a/lib/jnpr/jsnapy/jsnapy.py +++ b/lib/jnpr/jsnapy/jsnapy.py @@ -51,8 +51,7 @@ def __init__(self): self.test_cases = None self.parser = argparse.ArgumentParser( formatter_class=argparse.RawTextHelpFormatter, - description=textwrap.dedent( - """\ + description=textwrap.dedent("""\ Tool to capture snapshots and compare them It supports four subcommands: --snap, --check, --snapcheck, --diff @@ -64,8 +63,7 @@ def __init__(self): jsnapy --snapcheck snapfile -f main_configfile 4. Take diff without specifying test case: jsnapy --diff pre_snapfile post_snapfile -f main_configfile - """ - ), + """), usage="\nThis tool enables you to capture and audit runtime environment of " "\nnetworked devices running the Junos operating system (Junos OS)\n", ) @@ -139,15 +137,13 @@ def __init__(self): "-v", "--verbosity", action="count", - help=textwrap.dedent( - """\ + help=textwrap.dedent("""\ Set verbosity -v: Debug level messages -vv: Info level messages -vvv: Warning level messages -vvvv: Error level messages - -vvvvv: Critical level messages""" - ), + -vvvvv: Critical level messages"""), ) # self.parser.add_argument( # "-m", @@ -426,7 +422,7 @@ def compare_tests( pre_snap=None, post_snap=None, action=None, - **kwargs + **kwargs, ): """ called by check and snapcheck argument, to compare snap files @@ -617,7 +613,7 @@ def connect( config_data=None, action=None, post_snap=None, - **kwargs + **kwargs, ): """ connect to device and calls the function either to generate snapshots @@ -661,7 +657,7 @@ def connect( user=username, passwd=password, gather_facts=False, - **kwargs + **kwargs, ) try: dev.open() @@ -678,7 +674,7 @@ def connect( config_data, action, post_snap, - **kwargs + **kwargs, ) else: self.logger.error( @@ -996,7 +992,7 @@ def check_arguments(self): # then it should print error message. if not ( (self.args.file is None) - and ((self.args.testfiles is None or self.args.hostname is None)) + and (self.args.testfiles is None or self.args.hostname is None) ): action = None if self.set_action_cmd(action) is not None: diff --git a/lib/jnpr/jsnapy/operator.py b/lib/jnpr/jsnapy/operator.py index 156a707..3d74a5d 100755 --- a/lib/jnpr/jsnapy/operator.py +++ b/lib/jnpr/jsnapy/operator.py @@ -54,7 +54,7 @@ def define_operator( iter, id, test_name, - *args + *args, ): """ It will call functions according to test operator @@ -82,7 +82,7 @@ def define_operator( iter, id, test_name, - *args + *args, ) except AttributeError as e: self.logger_testop.error( diff --git a/lib/jnpr/jsnapy/sqlite_store.py b/lib/jnpr/jsnapy/sqlite_store.py index 5bf79a8..bf9ab31 100755 --- a/lib/jnpr/jsnapy/sqlite_store.py +++ b/lib/jnpr/jsnapy/sqlite_store.py @@ -23,17 +23,14 @@ def __init__(self, host, db_name): try: with sqlite3.connect(self.db_filename) as conn: # Creating schema if it does not exists - sqlstr = ( - """create table if not exists '%s' ( + sqlstr = """create table if not exists '%s' ( id integer not null, filename text, cli_command text, snap_name text, data_format text, data text - );""" - % self.table_name - ) + );""" % self.table_name conn.execute(sqlstr) except Exception as ex: self.logger_storesqlite.error( From 884f423d068f671d2423cbbf816d7e0027fbe213 Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Tue, 5 May 2026 03:34:15 -0700 Subject: [PATCH 3/6] issues and pull request templates --- requirements.txt | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0034a92..0ed62e6 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +setuptools colorama configparser pyparsing diff --git a/setup.py b/setup.py index 465da77..86f561b 100755 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def set_logging_path(path): ) elif "win32" in sys.platform: value["filename"] = os.path.join( - os.path.expanduser("~"), "logs\jsnapy\jsnapy.log" + os.path.expanduser("~"), "logs", "jsnapy", "jsnapy.log" ) with open(path, "w") as dump_f: From d8a8a3293a0fe5772591db94a7827a67f913638c Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Tue, 5 May 2026 03:44:19 -0700 Subject: [PATCH 4/6] issues and pull request templates --- .github/workflows/pylint.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index d3aac67..342ffc8 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -17,9 +17,9 @@ jobs: python-version: [3.8.12, 3.9.12, 3.10.12, 3.11.9, 3.12.4] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Validate version @@ -46,7 +46,7 @@ jobs: cd ../ tar -xzvf jsnapy-*.tar.gz cd jsnapy-1.3.8 - python setup.py install + pip install . - name: Analysing the code with pylint From 15b7d21dd53fda8643cc9ba5e88f0ecd9c918463 Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Thu, 25 Jun 2026 00:06:01 -0700 Subject: [PATCH 5/6] issues and pull request templates --- .github/workflows/pylint.yml | 2 +- development.txt | 1 + lib/jnpr/jsnapy/check.py | 2 +- lib/jnpr/jsnapy/jsnapy.py | 12 ++++++++---- lib/jnpr/jsnapy/sqlite_store.py | 7 +++++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 342ffc8..6b49ce9 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -56,7 +56,7 @@ jobs: - name: Run black tool run: | - pip install -U black; + pip install black==24.10.0; black --check --diff --exclude="docs|build|tests|samples|venv" . - name: Run unit test diff --git a/development.txt b/development.txt index 479f8b1..1dc6f74 100644 --- a/development.txt +++ b/development.txt @@ -1,5 +1,6 @@ -r requirements.txt +black==24.10.0 # pinned: last version supporting Python 3.8 coverage # http://nedbatchelder.com/code/coverage/ mock==1.0.1 # http://www.voidspace.org.uk/python/mock/ nose # http://nose.readthedocs.org/en/latest/ diff --git a/lib/jnpr/jsnapy/check.py b/lib/jnpr/jsnapy/check.py index 80918b0..42abf83 100755 --- a/lib/jnpr/jsnapy/check.py +++ b/lib/jnpr/jsnapy/check.py @@ -245,7 +245,7 @@ def expression_evaluator( # default error and info message err_mssg = self.get_err_mssg(elem_test, ele_list) info_mssg = self.get_info_mssg(elem_test, ele_list) - ignore_null = elem_test.get("ignore-null") or top_ignore_null + ignore_null = elem_test.get("ignore-null", top_ignore_null) # check test operators, below mentioned four are allowed only # with --check #### is_skipped = False diff --git a/lib/jnpr/jsnapy/jsnapy.py b/lib/jnpr/jsnapy/jsnapy.py index fcbebc5..70af893 100755 --- a/lib/jnpr/jsnapy/jsnapy.py +++ b/lib/jnpr/jsnapy/jsnapy.py @@ -51,7 +51,8 @@ def __init__(self): self.test_cases = None self.parser = argparse.ArgumentParser( formatter_class=argparse.RawTextHelpFormatter, - description=textwrap.dedent("""\ + description=textwrap.dedent( + """\ Tool to capture snapshots and compare them It supports four subcommands: --snap, --check, --snapcheck, --diff @@ -63,7 +64,8 @@ def __init__(self): jsnapy --snapcheck snapfile -f main_configfile 4. Take diff without specifying test case: jsnapy --diff pre_snapfile post_snapfile -f main_configfile - """), + """ + ), usage="\nThis tool enables you to capture and audit runtime environment of " "\nnetworked devices running the Junos operating system (Junos OS)\n", ) @@ -137,13 +139,15 @@ def __init__(self): "-v", "--verbosity", action="count", - help=textwrap.dedent("""\ + help=textwrap.dedent( + """\ Set verbosity -v: Debug level messages -vv: Info level messages -vvv: Warning level messages -vvvv: Error level messages - -vvvvv: Critical level messages"""), + -vvvvv: Critical level messages""" + ), ) # self.parser.add_argument( # "-m", diff --git a/lib/jnpr/jsnapy/sqlite_store.py b/lib/jnpr/jsnapy/sqlite_store.py index bf9ab31..5bf79a8 100755 --- a/lib/jnpr/jsnapy/sqlite_store.py +++ b/lib/jnpr/jsnapy/sqlite_store.py @@ -23,14 +23,17 @@ def __init__(self, host, db_name): try: with sqlite3.connect(self.db_filename) as conn: # Creating schema if it does not exists - sqlstr = """create table if not exists '%s' ( + sqlstr = ( + """create table if not exists '%s' ( id integer not null, filename text, cli_command text, snap_name text, data_format text, data text - );""" % self.table_name + );""" + % self.table_name + ) conn.execute(sqlstr) except Exception as ex: self.logger_storesqlite.error( From 729a8e6a120b034d51f0dd3233fca0310e68cee4 Mon Sep 17 00:00:00 2001 From: chidanandpujar Date: Thu, 25 Jun 2026 03:11:38 -0700 Subject: [PATCH 6/6] issues and pull request templates --- .github/workflows/pylint.yml | 2 +- development.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 6b49ce9..711c9b4 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -56,7 +56,7 @@ jobs: - name: Run black tool run: | - pip install black==24.10.0; + pip install black==24.8.0; black --check --diff --exclude="docs|build|tests|samples|venv" . - name: Run unit test diff --git a/development.txt b/development.txt index 1dc6f74..c9d8953 100644 --- a/development.txt +++ b/development.txt @@ -1,6 +1,6 @@ -r requirements.txt -black==24.10.0 # pinned: last version supporting Python 3.8 +black==24.8.0 # pinned: last version supporting Python 3.8 (24.10.0 requires >=3.9) coverage # http://nedbatchelder.com/code/coverage/ mock==1.0.1 # http://www.voidspace.org.uk/python/mock/ nose # http://nose.readthedocs.org/en/latest/