From 15e023d6e69e90d47d309909a0eb3da76d5df055 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 1 Sep 2024 21:33:26 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20[external=5Fapi=5Fchang?= =?UTF-8?q?e]=20Updated=20to=20copier-ProjectScaffolding=20v0.2.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .copier-answers.yml | 32 ++ .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 32 ++ .github/ISSUE_TEMPLATE/config.yml | 1 + .github/ISSUE_TEMPLATE/custom.md | 8 + .github/ISSUE_TEMPLATE/feature_request.md | 20 + .github/pull_request_template.md | 8 + .github/release_sources.yaml | 10 +- .github/workflows/codeql.yml | 174 +++---- .../workflows/{standard.yaml => standard.yml} | 473 +++++++++--------- .gitignore | 36 +- .python_project_bootstrapper_config.yml | 22 - .python_project_bootstrapper_manifest.yml | 29 -- ActivateEpilog.py | 22 +- Bootstrap.cmd | 228 ++++----- BootstrapEpilog.py | 94 ++-- Build.py | 164 +++--- CODE_OF_CONDUCT.md | 25 + CONTRIBUTING.md | 97 ++-- DEVELOPMENT.md | 117 +++-- GOVERNANCE.md | 2 + LICENSE.txt | 42 +- MAINTAINERS.md | 14 + README.md | 162 +++--- SECURITY.md | 18 +- minisign_key.pub | 2 + pyproject.toml | 389 +++++++------- src/AutoGitSemVer.yaml | 12 +- src/BuildBinary.py | 197 ++++---- 29 files changed, 1250 insertions(+), 1181 deletions(-) create mode 100644 .copier-answers.yml create mode 100644 .github/CODEOWNERS create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/custom.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md rename .github/workflows/{standard.yaml => standard.yml} (83%) delete mode 100644 .python_project_bootstrapper_config.yml delete mode 100644 .python_project_bootstrapper_manifest.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 GOVERNANCE.md create mode 100644 MAINTAINERS.md create mode 100644 minisign_key.pub diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..7f68324 --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,32 @@ +# Changes here will be overwritten by Copier; DO NOT MODIFY THIS FILE DIRECTLY! +# +# This file was generated using copier (https://copier.readthedocs.io/) with the +# template copier-ProjectScaffolding (https://github.com/gt-sse-center/copier-ProjectScaffolding). +# Additional information (including instructions on how to use this template with copier) is +# available at https://github.com/gt-sse-center/copier-ProjectScaffolding. +# + +_commit: v0.2.6 +_src_path: https://github.com/gt-sse-center/copier-ProjectScaffolding +author_email: github@DavidBrownell.com +author_name: David Brownell +documentation_license: MIT +generate_docs: true +github_host: https://github.com +github_repo_name: FileBackup +github_username: davidbrownell +hosting_platform: GitHub +project_description: Tool for creating and restoring file system backups. +project_name: FileBackup +project_type: PythonPackage +python_package_generate_ci_binary_question: true +python_package_generate_ci_docker_image_question: true +python_package_generate_ci_openssf_id: '9069' +python_package_generate_ci_openssf_question: true +python_package_generate_ci_persist_coverage_gist_id: f15146b1b8fdc0a5d45ac0eb786a84f7 +python_package_generate_ci_persist_coverage_gist_username: davidbrownell +python_package_generate_ci_persist_coverage_question: true +python_package_generate_ci_question: true +python_package_generate_ci_sign_artifacts_question: true +python_package_pypi_name: FileBackup +repository_tool: git diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..39f9bd0 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @davidbrownell diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..b9cb379 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: '' +labels: '' +assignees: '' + +--- + +## Describe the bug +A clear and concise description of what the bug is. + +## To Reproduce +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +## Expected behavior +A clear and concise description of what you expected to happen. + +## Screenshots +If applicable, add screenshots to help explain your problem. + +## Environment (please complete the following information): + - OS: [e.g. iOS] + - Python Version: [e.g. 3.12, 3.11, etc.] + - FileBackup Version [e.g. 1.2.3] + +## Additional context +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3ba13e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000..0b06d6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,8 @@ +--- +name: Custom issue template +about: Create an issue that isn't a bug or feature request. +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7de3fe0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project. +title: '' +labels: '' +assignees: '' + +--- + +## Is your feature request related to a problem? Please describe. +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +## Describe the solution you'd like +A clear and concise description of what you want to happen. + +## Describe alternatives you've considered +A clear and concise description of any alternative solutions or features you've considered. + +## Additional context +Add any other context or screenshots about the feature request here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..a69cfa2 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +## :pencil: Description +Please include a summary of the change and the work item associated with it. + +## :gear: Work Item +Please include link to the corresponding GitHub Issue or Project work item. + +## :movie_camera: Demo +Please provide any images, GIFs, or videos that show the effect of your changes (if applicable). A picture is worth a thousand words. diff --git a/.github/release_sources.yaml b/.github/release_sources.yaml index d89aeb1..3df6937 100644 --- a/.github/release_sources.yaml +++ b/.github/release_sources.yaml @@ -1,5 +1,5 @@ -# Changes to any file or a file within a directory will trigger a release. -src: - - 'src/**' - - 'pyproject.toml' - - 'README.md' +# Changes to any of these files or a file within these directories will trigger a release. +src: + - 'src/**' + - 'pyproject.toml' + - 'README.md' diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 82dd2bf..2671f30 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,87 +1,87 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '0 0 * * *' - workflow_dispatch: - -permissions: {} - -jobs: - analyze: - name: Analyze - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners - # Consider using larger runners for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - # required for all workflows - security-events: write - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - language: [ 'python' ] - # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] - # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: {} + +jobs: + analyze: + name: Analyze + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners + # Consider using larger runners for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + language: [ 'python' ] + # CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ] + # Use only 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/standard.yaml b/.github/workflows/standard.yml similarity index 83% rename from .github/workflows/standard.yaml rename to .github/workflows/standard.yml index d87d27d..ddfdb27 100644 --- a/.github/workflows/standard.yaml +++ b/.github/workflows/standard.yml @@ -1,241 +1,232 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 David Brownell -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -name: "Standard" - -run-name: ${{ github.run_number }} [${{ github.actor }}] on ${{ github.ref_name }} - -on: - pull_request: - branches: - - main - push: - branches: - - main - schedule: - - cron: '0 0 * * *' # Once a day at 12am UTC - workflow_dispatch: - -permissions: {} - -jobs: - # ---------------------------------------------------------------------- - action_contexts: - name: "Display GitHub Action Contexts" - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.20.0 - - # ---------------------------------------------------------------------- - validate: - strategy: - fail-fast: false - - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - - python_version: - - "3.12" - - "3.11" - - "3.10" - # - "3.9" # Not supported - # - "3.8" # Not supported - - name: Validate - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.20.0 - with: - operating_system: ${{ matrix.os }} - python_version: ${{ matrix.python_version }} - - # ---------------------------------------------------------------------- - package_coverage: - needs: validate - - name: Postprocess Coverage Info - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.20.0 - with: - gist_id: f15146b1b8fdc0a5d45ac0eb786a84f7 - gist_filename: FileBackup_coverage.json - secrets: - GIST_TOKEN: ${{ secrets.GIST_TOKEN }} - - # ---------------------------------------------------------------------- - create_package: - needs: validate - - strategy: - fail-fast: false - - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - - python_version: - - "3.12" - - "3.11" - - "3.10" - # - "3.9" # Not supported - # - "3.8" # Not supported - - name: Create Package - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.20.0 - with: - operating_system: ${{ matrix.os }} - python_version: ${{ matrix.python_version }} - - # ---------------------------------------------------------------------- - validate_package: - needs: create_package - - strategy: - fail-fast: false - - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - - python_version: - - "3.12" - - "3.11" - - "3.10" - # - "3.9" # Not supported - # - "3.8" # Not supported - - name: Validate Package - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.20.0 - with: - operating_system: ${{ matrix.os }} - python_version: ${{ matrix.python_version }} - validation_command: python -c "from FileBackup import __version__; print(__version__)" - - # ---------------------------------------------------------------------- - create_binary: - needs: validate - - strategy: - fail-fast: false - - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - - python_version: - - "3.11" - - name: Create Binary - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.20.0 - with: - operating_system: ${{ matrix.os }} - python_version: ${{ matrix.python_version }} - - # ---------------------------------------------------------------------- - validate_binary: - needs: create_binary - - strategy: - fail-fast: false - - matrix: - os: - - macos-latest - - ubuntu-latest - - windows-latest - - python_version: - - "3.11" - - name: Validate Binary - - permissions: - contents: read - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.20.0 - with: - operating_system: ${{ matrix.os }} - python_version: ${{ matrix.python_version }} - validation_command: FileBackup version - - -# ---------------------------------------------------------------------- - create_docker_image: - needs: validate - - strategy: - fail-fast: false - - matrix: - python_version: - - "3.12" - - "3.11" - - "3.10" - # - "3.9" # Not supported - # - "3.8" # Not supported - - name: Create Docker Image - - permissions: - contents: read - packages: write - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_docker_image.yaml@CI-v0.20.0 - with: - operating_system: ubuntu-latest - python_version: ${{ matrix.python_version }} - name_suffix: -${{ matrix.python_version }} - bootstrap_args: "" - docker_description: "FileBackup - ${{ matrix.python_version }}" - push_image_as_package: true - container_registry_username: davidbrownell - - - # ---------------------------------------------------------------------- - publish: - needs: - - validate_package - - validate_binary - - - create_docker_image - - - name: Publish - - permissions: - contents: write - - uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.20.0 - with: - release_sources_configuration_filename: .github/release_sources.yaml - secrets: - PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - - MINISIGN_PRIVATE_KEY: ${{ secrets.MINISIGN_PRIVATE_KEY }} +name: "Standard" + +run-name: ${{ github.run_number }} [${{ github.actor }}] on ${{ github.ref_name }} + +on: + pull_request: + branches: + - main + push: + branches: + - main + schedule: + - cron: '0 0 * * *' # Once a day at 12am UTC + workflow_dispatch: + +permissions: {} + +jobs: + # ---------------------------------------------------------------------- + action_contexts: + name: "Display GitHub Action Contexts" + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_display_action_contexts.yaml@CI-v0.22.1 + + # ---------------------------------------------------------------------- + validate: + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + + python_version: + - "3.12" + - "3.11" + - "3.10" + # - "3.9" # Not supported + # - "3.8" # Not supported + + name: Validate + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python.yaml@CI-v0.22.1 + with: + operating_system: ${{ matrix.os }} + python_version: ${{ matrix.python_version }} + + # ---------------------------------------------------------------------- + package_coverage: + needs: validate + + name: Postprocess Coverage Info + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_package_python_coverage.yaml@CI-v0.22.1 + with: + gist_id: f15146b1b8fdc0a5d45ac0eb786a84f7 + gist_filename: FileBackup_coverage.json + secrets: + GIST_TOKEN: ${{ secrets.GIST_TOKEN }} + + # ---------------------------------------------------------------------- + create_package: + needs: package_coverage + + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + + python_version: + - "3.12" + - "3.11" + - "3.10" + # - "3.9" # Not supported + # - "3.8" # Not supported + + name: Create Package + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_package.yaml@CI-v0.22.1 + with: + operating_system: ${{ matrix.os }} + python_version: ${{ matrix.python_version }} + + # ---------------------------------------------------------------------- + validate_package: + needs: create_package + + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + + python_version: + - "3.12" + - "3.11" + - "3.10" + # - "3.9" # Not supported + # - "3.8" # Not supported + + name: Validate Package + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_package.yaml@CI-v0.22.1 + with: + operating_system: ${{ matrix.os }} + python_version: ${{ matrix.python_version }} + validation_command: python -c "from FileBackup import __version__; print(__version__)" + + # ---------------------------------------------------------------------- + create_binary: + needs: package_coverage + + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + + python_version: + - "3.11" + + name: Create Binary + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_python_binary.yaml@CI-v0.22.1 + with: + operating_system: ${{ matrix.os }} + python_version: ${{ matrix.python_version }} + + # ---------------------------------------------------------------------- + validate_binary: + needs: create_binary + + strategy: + fail-fast: false + + matrix: + os: + - macos-latest + - ubuntu-latest + - windows-latest + + python_version: + - "3.11" + + name: Validate Binary + + permissions: + contents: read + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_validate_python_binary.yaml@CI-v0.22.1 + with: + operating_system: ${{ matrix.os }} + python_version: ${{ matrix.python_version }} + validation_command: FileBackup version + + + # ---------------------------------------------------------------------- + create_docker_image: + needs: package_coverage + + strategy: + fail-fast: false + + matrix: + python_version: + - "3.12" + - "3.11" + - "3.10" + # - "3.9" # Not supported + # - "3.8" # Not supported + + name: Create Docker Image + + permissions: + contents: read + packages: write + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_create_docker_image.yaml@CI-v0.22.1 + with: + operating_system: ubuntu-latest + python_version: ${{ matrix.python_version }} + name_suffix: -${{ matrix.python_version }} + bootstrap_args: "" + docker_description: "FileBackup - ${{ matrix.python_version }}" + push_image_as_package: true + container_registry_username: davidbrownell + + + # ---------------------------------------------------------------------- + publish: + needs: + - validate_package + - validate_binary + - create_docker_image + + name: Publish + + permissions: + contents: write + + uses: davidbrownell/dbrownell_DevTools/.github/workflows/callable_publish_python.yaml@CI-v0.22.1 + with: + release_sources_configuration_filename: .github/release_sources.yaml + secrets: + PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} + MINISIGN_PRIVATE_KEY: ${{ secrets.MINISIGN_PRIVATE_KEY }} diff --git a/.gitignore b/.gitignore index 41ed221..8e9d6c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,19 @@ -Activate*.cmd -Activate*.sh -Deactivate*.cmd -Deactivate*.sh - -**/__pycache__/** -**/Generated/** -**/.coverage -**/lcov.info -**/.vscode - -build/** -dist/** -src/FileBackup.egg-info/** - -minisign_key.pri -minisign_key.pub +post_generation_actions.html + +Activate*.cmd +Activate*.sh +Deactivate*.cmd +Deactivate*.sh + +**/__pycache__/** +**/Generated/** + +**/.coverage +**/lcov.info +**/.vscode + +build/** +dist/** +src/FileBackup.egg-info/** + +minisign_key.pri diff --git a/.python_project_bootstrapper_config.yml b/.python_project_bootstrapper_config.yml deleted file mode 100644 index 710c018..0000000 --- a/.python_project_bootstrapper_config.yml +++ /dev/null @@ -1,22 +0,0 @@ -############################################################################################################# -# This file is used by PythonProjectBootstrapper (https://github.com/gt-sse-center/PythonProjectBootstrapper) -# to rerun generation on this python package. To use this file, run the following command from within this -# working directory: -# -# PythonProjectBootstrapper package . --config .python_project_bootstrapper_config.yml -# -############################################################################################################# -default_context: - name: David Brownell - email: db@DavidBrownell.com - project_description: Tool for creating and restoring file system backups. - license: MIT - github_url: https://github.com - github_username: davidbrownell - github_project_name: FileBackup - pypi_project_name: FileBackup - gist_id: f15146b1b8fdc0a5d45ac0eb786a84f7 - gist_username: davidbrownell - minisign_public_key: RWTO8gifpEKQhwiguxsldM47Php1GeTs0foueIpaLPp0xSy0N5FBn/70 - openssf_best_practices_badge_id: 9069 - create_docker_image: True diff --git a/.python_project_bootstrapper_manifest.yml b/.python_project_bootstrapper_manifest.yml deleted file mode 100644 index fa59294..0000000 --- a/.python_project_bootstrapper_manifest.yml +++ /dev/null @@ -1,29 +0,0 @@ -############################################################################################################# -# This file is used by PythonProjectBootstrapper (https://github.com/gt-sse-center/PythonProjectBootstrapper) -# to determine whether changes have been made to any files in the project. These values are saved in case the -# project is regenerated so we can avoid overwriting any user changes. Please do not change the contents :) -############################################################################################################# - -.github/release_sources.yaml: c2241d25423ec6e22afa41c6caed30162438af803e6de74ee466479ca6cd8246 -.github/workflows/codeql.yml: 5e6e94a06f17ebbd8d3042467327837bb2076c29a1414b794800a3c1b09cca7d -.github/workflows/standard.yaml: 9b11066818a63fa28c19fae3b85f6737b8b805e40fd35635477af34ed40b93ea -.gitignore: 4431dbdb4c35765df68c0084dd823a53749423267d3174b031f285df71049a87 -.python_project_bootstrapper_config.yml: 80ac560edbf136640da3cd66f0d0ea629ef052d095c6ebb26743a01c6559e0d5 -ActivateEpilog.py: 102bb407fb3efcdbb697c4c5ea0d98236d43490ff9297bfa00b37ffaed66501d -Bootstrap.cmd: 48a673262f121c847d924d9b4b1db2a7ee01ef46d0aca8912d0c90f1f1d464c1 -Bootstrap.sh: c68ba07e6ab2df55c54a0285becf8c510cba9d0738f7c1b59b24a6188bb486f8 -BootstrapEpilog.py: 36b346de7e14228f4481f22e080798f86db482e4dc1487cb811bec1c559f8c32 -Build.py: 86ed55a96e861080d081c849509aeed3b21737532a822fbad83afb6bc12e807a -CONTRIBUTING.md: 6eaefdb9d02248370002b946eacaad8b3b78c138ebe899b54301378f5ca08a0a -DEVELOPMENT.md: a32e71d167a0a268b3fbb65ff3d629433034984bc377a5161bde78f532f18020 -LICENSE.txt: 3f47ea184270561e800e5be15ac3cdc705882363b455aa3230a51c8c3aac38e3 -README.md: 13a84346d6c86d3c46d615856a9f83552b47b64e19e6002bdcd852606be11c03 -SECURITY.md: ee3b8fc170428b5de0ea90006621bfde59ecc973728ce7f2161f0c677f3a29b1 -pyproject.toml: 1fa8fbfcfdba7127d05b467a6a27de8eee6c5f6f76e7da4ba209e94e4ad23d95 -src/AutoGitSemVer.yaml: de69caf0ae3fa7fffc5c7b0d9dd7c4a566fd0e7ba1d8bd5040774f9c056b7add -src/BuildBinary.py: e74a864ad4bbd482dfb4d738919a8b3077e6c4bef5ef9c5fe9cb89d391ff996a -src/FileBackup/EntryPoint.py: d378188caa00c8a8e6d4c98abe6e8be9a31b678cba3b8d4809020afb30375865 -src/FileBackup/Math.py: 32d808f59d0d46a183b6d4e87f333650f943deee0b9bdd69c4a5f90e5eb99c84 -src/FileBackup/__init__.py: d5988b69e5156d346b33d9ffb60ea2b7fa8909b684514bcff90c12668845f598 -tests/EntryPoint_UnitTest.py: 3c97a9fb5359d5fe8eb9a3bbcf382ceb146c85554a146c60ccce0ba5d72d8448 -tests/Math_UnitTest.py: d46f3c9e40967faa832a10e0c8619846712ccf3c4d3cda0778474de690797a38 diff --git a/ActivateEpilog.py b/ActivateEpilog.py index 9a47b2a..53cd10d 100644 --- a/ActivateEpilog.py +++ b/ActivateEpilog.py @@ -1,11 +1,11 @@ -import json -import os -import sys - -from pathlib import Path - -with (Path(os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"]) / "bootstrap_flags.json").open() as f: - flags = json.load(f) - -if flags: - sys.stdout.write("\nBootstrapped with {}.\n".format(", ".join(f"'{flag}'" for flag in flags))) +import json +import os +import sys + +from pathlib import Path + +with (Path(os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"]) / "bootstrap_flags.json").open() as f: + flags = json.load(f) + +if flags: + sys.stdout.write("\nBootstrapped with {}.\n".format(", ".join(f"'{flag}'" for flag in flags))) diff --git a/Bootstrap.cmd b/Bootstrap.cmd index 185c3f9..81760d1 100644 --- a/Bootstrap.cmd +++ b/Bootstrap.cmd @@ -1,114 +1,114 @@ -@REM ---------------------------------------------------------------------- -@REM | -@REM | This script downloads and invokes BoostrapImpl.cmd from the PythonBootstrapper -@REM | repository (https://github.com/davidbrownell/PythonBootstrapper). -@REM | -@REM | Arguments: -@REM | -@REM | --debug Display additional debugging information. -@REM | -@REM | --force Ensure that a new python environment is installed, even if it already exists. -@REM | -@REM | --python-version Specify the python version to install; the default python version is installed if not specified. -@REM | -@REM | --bootstrap-branch Specify the branch of the PythonBootstrapper repository to use when downloading BootstrapImpl; "main" is used if not specified. -@REM | -@REM ---------------------------------------------------------------------- -@setlocal EnableDelayedExpansion -@pushd %~dp0 - -@REM ---------------------------------------------------------------------- -@REM | -@REM | Parse and Process Arguments -@REM | -@REM ---------------------------------------------------------------------- -@set _BOOTSTRAP_BRANCH=main -@set _COMMAND_LINE_ARGS= - -:ParseArgs -@if '%1' EQU '' @goto :ParseArgs_End - -@set ARG=%1 -@set ARG=%ARG:"=% - -@if "%ARG%" NEQ "--bootstrap-branch" @goto :ParseArgs_BootstrapBranchEnd - -@REM Extract the bootstrap branch -@shift /1 - -@set ARG=%1 -@set ARG=%ARG:"=% - -@set _BOOTSTRAP_BRANCH=%ARG% -@goto :ParseArgs_Next - -:ParseArgs_BootstrapBranchEnd -@set _COMMAND_LINE_ARGS=%_COMMAND_LINE_ARGS% %1 - -:ParseArgs_Next -@shift /1 -@goto :ParseArgs - -:ParseArgs_End - -@REM ---------------------------------------------------------------------- -@REM | -@REM | Download BootstrapImpl.cmd -@REM | -@REM ---------------------------------------------------------------------- -@echo Downloading Bootstrap code... - -@set _BOOTSTRAPIMPL_URL=https://raw.githubusercontent.com/davidbrownell/PythonBootstrapper/%_BOOTSTRAP_BRANCH%/src/BootstrapImpl.cmd - -@call :_CreateTempFileName - -@curl --header "Cache-Control: no-cache, no-store" --header "Pragma: no-cache" --location %_BOOTSTRAPIMPL_URL% --output BootstrapImpl.cmd --no-progress-meter --fail-with-body > "%_BOOTSTRAP_TEMP_FILENAME%" 2>&1 -@set _ERRORLEVEL=%ERRORLEVEL% - -@if %_ERRORLEVEL% NEQ 0 ( - @echo Downloading Bootstrap code...FAILED ^(%_BOOTSTRAPIMPL_URL%^). - @echo. - - @type "%_BOOTSTRAP_TEMP_FILENAME%" - @goto :Exit -) - -@call :_DeleteTempFile -@echo Downloading Bootstrap code...DONE. - -@REM ---------------------------------------------------------------------- -@REM | -@REM | Invoke BootstrapImpl.cmd -@REM | -@REM ---------------------------------------------------------------------- -@call BootstrapImpl.cmd %_COMMAND_LINE_ARGS% -@set _ERRORLEVEL=%ERRORLEVEL% - -@REM ---------------------------------------------------------------------- -@REM | -@REM | Exit -@REM | -@REM ---------------------------------------------------------------------- -:Exit -@if exist BootstrapImpl.cmd del BootstrapImpl.cmd -@call :_DeleteTempFile - -@popd - -@endlocal & @exit /B %_ERRORLEVEL% - -@REM ---------------------------------------------------------------------- -@REM ---------------------------------------------------------------------- -@REM ---------------------------------------------------------------------- -:_CreateTempFileName -@set _BOOTSTRAP_TEMP_FILENAME=%CD%\Bootstrap-!RANDOM!-!Time:~6,5! -@goto :EOF - -@REM ---------------------------------------------------------------------- -:_DeleteTempFile -@if "%_BOOTSTRAP_TEMP_FILENAME%" NEQ "" ( - @if exist "%_BOOTSTRAP_TEMP_FILENAME%" ( - @del "%_BOOTSTRAP_TEMP_FILENAME%" - ) -) -@goto :EOF +@REM ---------------------------------------------------------------------- +@REM | +@REM | This script downloads and invokes BoostrapImpl.cmd from the PythonBootstrapper +@REM | repository (https://github.com/davidbrownell/PythonBootstrapper). +@REM | +@REM | Arguments: +@REM | +@REM | --debug Display additional debugging information. +@REM | +@REM | --force Ensure that a new python environment is installed, even if it already exists. +@REM | +@REM | --python-version Specify the python version to install; the default python version is installed if not specified. +@REM | +@REM | --bootstrap-branch Specify the branch of the PythonBootstrapper repository to use when downloading BootstrapImpl; "main" is used if not specified. +@REM | +@REM ---------------------------------------------------------------------- +@setlocal EnableDelayedExpansion +@pushd %~dp0 + +@REM ---------------------------------------------------------------------- +@REM | +@REM | Parse and Process Arguments +@REM | +@REM ---------------------------------------------------------------------- +@set _BOOTSTRAP_BRANCH=main +@set _COMMAND_LINE_ARGS= + +:ParseArgs +@if '%1' EQU '' @goto :ParseArgs_End + +@set ARG=%1 +@set ARG=%ARG:"=% + +@if "%ARG%" NEQ "--bootstrap-branch" @goto :ParseArgs_BootstrapBranchEnd + +@REM Extract the bootstrap branch +@shift /1 + +@set ARG=%1 +@set ARG=%ARG:"=% + +@set _BOOTSTRAP_BRANCH=%ARG% +@goto :ParseArgs_Next + +:ParseArgs_BootstrapBranchEnd +@set _COMMAND_LINE_ARGS=%_COMMAND_LINE_ARGS% %1 + +:ParseArgs_Next +@shift /1 +@goto :ParseArgs + +:ParseArgs_End + +@REM ---------------------------------------------------------------------- +@REM | +@REM | Download BootstrapImpl.cmd +@REM | +@REM ---------------------------------------------------------------------- +@echo Downloading Bootstrap code... + +@set _BOOTSTRAPIMPL_URL=https://raw.githubusercontent.com/davidbrownell/PythonBootstrapper/%_BOOTSTRAP_BRANCH%/src/BootstrapImpl.cmd + +@call :_CreateTempFileName + +@curl --header "Cache-Control: no-cache, no-store" --header "Pragma: no-cache" --location %_BOOTSTRAPIMPL_URL% --output BootstrapImpl.cmd --no-progress-meter --fail-with-body > "%_BOOTSTRAP_TEMP_FILENAME%" 2>&1 +@set _ERRORLEVEL=%ERRORLEVEL% + +@if %_ERRORLEVEL% NEQ 0 ( + @echo Downloading Bootstrap code...FAILED ^(%_BOOTSTRAPIMPL_URL%^). + @echo. + + @type "%_BOOTSTRAP_TEMP_FILENAME%" + @goto :Exit +) + +@call :_DeleteTempFile +@echo Downloading Bootstrap code...DONE. + +@REM ---------------------------------------------------------------------- +@REM | +@REM | Invoke BootstrapImpl.cmd +@REM | +@REM ---------------------------------------------------------------------- +@call BootstrapImpl.cmd %_COMMAND_LINE_ARGS% +@set _ERRORLEVEL=%ERRORLEVEL% + +@REM ---------------------------------------------------------------------- +@REM | +@REM | Exit +@REM | +@REM ---------------------------------------------------------------------- +:Exit +@if exist BootstrapImpl.cmd del BootstrapImpl.cmd +@call :_DeleteTempFile + +@popd + +@endlocal & @exit /B %_ERRORLEVEL% + +@REM ---------------------------------------------------------------------- +@REM ---------------------------------------------------------------------- +@REM ---------------------------------------------------------------------- +:_CreateTempFileName +@set _BOOTSTRAP_TEMP_FILENAME=%CD%\Bootstrap-!RANDOM!-!Time:~6,5! +@goto :EOF + +@REM ---------------------------------------------------------------------- +:_DeleteTempFile +@if "%_BOOTSTRAP_TEMP_FILENAME%" NEQ "" ( + @if exist "%_BOOTSTRAP_TEMP_FILENAME%" ( + @del "%_BOOTSTRAP_TEMP_FILENAME%" + ) +) +@goto :EOF diff --git a/BootstrapEpilog.py b/BootstrapEpilog.py index 521c5ab..9aba079 100644 --- a/BootstrapEpilog.py +++ b/BootstrapEpilog.py @@ -1,56 +1,38 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 David Brownell -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -# pylint: disable=missing-module-docstring - -import os -import subprocess -import sys - -from pathlib import Path - - -# Parse the arguments -is_debug = False -is_force = False -is_verbose = False -is_package = False -no_cache = False - -display_flags: list[str] = [] - -# First arg is the script name, second arg is the name of the shell script to write to -for arg in sys.argv[2:]: - if arg == "--debug": - is_debug = True - elif arg == "--force": - is_force = True - elif arg == "--verbose": - is_verbose = True - elif arg == "--package": - is_package = True - display_flags.append("package") - elif arg == "--no-cache": - no_cache = True - else: - raise Exception("'{}' is not a recognized argument.".format(arg)) - -if is_debug: - is_verbose = True - -subprocess.run( - 'pip install --disable-pip-version-check {} --editable ".[dev{}]"'.format( - "--no-cache-dir" if no_cache else "", - ", package" if is_package else "", - ), - check=True, - shell=True, -) - -with ( - Path(__file__).parent / os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"] / "bootstrap_flags.json" -).open("w") as f: - f.write("[{}]".format(", ".join(f'"{flag}"' for flag in display_flags))) +# pylint: disable=missing-module-docstring + +import os +import subprocess +import sys + +from pathlib import Path + + +# Parse the arguments +is_package = False +no_cache = False + +display_flags: list[str] = [] + +# First arg is the script name, second arg is the name of the shell script to write to +for arg in sys.argv[2:]: + if arg == "--package": + is_package = True + display_flags.append("package") + elif arg == "--no-cache": + no_cache = True + else: + sys.stderr.write(f"WARNING: '{arg}' is not a recognized argument.\n") + +subprocess.run( + 'pip install --disable-pip-version-check {} --editable ".[dev{}]"'.format( + "--no-cache-dir" if no_cache else "", + ", package" if is_package else "", + ), + check=True, + shell=True, +) + +with ( + Path(__file__).parent / os.environ["PYTHON_BOOTSTRAPPER_GENERATED_DIR"] / "bootstrap_flags.json" +).open("w") as f: + f.write("[{}]".format(", ".join(f'"{flag}"' for flag in display_flags))) diff --git a/Build.py b/Build.py index 89efde2..faf5912 100644 --- a/Build.py +++ b/Build.py @@ -1,85 +1,79 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 David Brownell -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -"""Build tasks for this python project.""" - -import sys - -from pathlib import Path - -import typer - -from dbrownell_Common import PathEx -from dbrownell_DevTools.RepoBuildTools import Python as RepoBuildTools -from typer.core import TyperGroup - - -# ---------------------------------------------------------------------- -class NaturalOrderGrouper(TyperGroup): - # pylint: disable=missing-class-docstring - # ---------------------------------------------------------------------- - def list_commands(self, *args, **kwargs): # pylint: disable=unused-argument - return self.commands.keys() - - -# ---------------------------------------------------------------------- -app = typer.Typer( - cls=NaturalOrderGrouper, - help=__doc__, - no_args_is_help=True, - pretty_exceptions_show_locals=False, - pretty_exceptions_enable=False, -) - - -# ---------------------------------------------------------------------- -this_dir = PathEx.EnsureDir(Path(__file__).parent) -src_dir = PathEx.EnsureDir(this_dir / "src") -package_dir = PathEx.EnsureDir(src_dir / "FileBackup") - - -# ---------------------------------------------------------------------- -Black = RepoBuildTools.BlackFuncFactory(this_dir, app) - -Pylint = RepoBuildTools.PylintFuncFactory( - package_dir, - app, - default_min_score=9.5, -) - -Pytest = RepoBuildTools.PytestFuncFactory( - this_dir, - package_dir.name, - app, - default_min_coverage=87.0, # TODO: Increase this to 90% -) - -UpdateVersion = RepoBuildTools.UpdateVersionFuncFactory( - src_dir, - PathEx.EnsureFile(package_dir / "__init__.py"), - app, -) - -Package = RepoBuildTools.PackageFuncFactory(this_dir, app) -Publish = RepoBuildTools.PublishFuncFactory(this_dir, app) - -BuildBinary = RepoBuildTools.BuildBinaryFuncFactory( - this_dir, - PathEx.EnsureFile(src_dir / "BuildBinary.py"), - app, -) - -CreateDockerImage = RepoBuildTools.CreateDockerImageFuncFactory( - this_dir, - app, -) - - -# ---------------------------------------------------------------------- -# ---------------------------------------------------------------------- -# ---------------------------------------------------------------------- -if __name__ == "__main__": - sys.exit(app()) +"""Build tasks for this python project.""" + +import sys + +from pathlib import Path + +import typer + +from dbrownell_Common import PathEx +from dbrownell_DevTools.RepoBuildTools import Python as RepoBuildTools +from typer.core import TyperGroup + + +# ---------------------------------------------------------------------- +class NaturalOrderGrouper(TyperGroup): + # pylint: disable=missing-class-docstring + # ---------------------------------------------------------------------- + def list_commands(self, *args, **kwargs): # pylint: disable=unused-argument + return self.commands.keys() + + +# ---------------------------------------------------------------------- +app = typer.Typer( + cls=NaturalOrderGrouper, + help=__doc__, + no_args_is_help=True, + pretty_exceptions_show_locals=False, + pretty_exceptions_enable=False, +) + + +# ---------------------------------------------------------------------- +this_dir = PathEx.EnsureDir(Path(__file__).parent) +src_dir = PathEx.EnsureDir(this_dir / "src") +package_dir = PathEx.EnsureDir(src_dir / "FileBackup") + + +# ---------------------------------------------------------------------- +Black = RepoBuildTools.BlackFuncFactory(this_dir, app) + +Pylint = RepoBuildTools.PylintFuncFactory( + package_dir, + app, + default_min_score=9.5, +) + +Pytest = RepoBuildTools.PytestFuncFactory( + this_dir, + package_dir.name, + app, + default_min_coverage=87.0, # TODO: Increase this to 90% +) + +UpdateVersion = RepoBuildTools.UpdateVersionFuncFactory( + src_dir, + PathEx.EnsureFile(package_dir / "__init__.py"), + app, +) + +Package = RepoBuildTools.PackageFuncFactory(this_dir, app) +Publish = RepoBuildTools.PublishFuncFactory(this_dir, app) + +BuildBinary = RepoBuildTools.BuildBinaryFuncFactory( + this_dir, + PathEx.EnsureFile(src_dir / "BuildBinary.py"), + app, +) + +CreateDockerImage = RepoBuildTools.CreateDockerImageFuncFactory( + this_dir, + app, +) + + +# ---------------------------------------------------------------------- +# ---------------------------------------------------------------------- +# ---------------------------------------------------------------------- +if __name__ == "__main__": + sys.exit(app()) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..3b2d0a7 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,25 @@ +# FileBackup Open Source Code of Conduct + +## Principles +These principles guide our data, product, and process decisions, architecture, and approach. + +- Open means transparent and participatory. +- We take a modular and modern approach to software development. +- We build open-source software and open-source process. +- We value ease of implementation. +- Fostering community includes building capacity and making our software and processes accessible to participants with diverse backgrounds and skillsets. +- Data (and data science) is as important as software and process. We build open data sets where possible. +- We strive for transparency for algorithms and places we might be introducing bias. + +## Community Guidelines +Information on contributing to this repository is available in our [Contributing file](CONTRIBUTING.md). + +When participating in FileBackup open source community conversations and spaces, we ask individuals to follow the following guidelines: + +- Embrace a culture of learning, and educate each other. We are all entering this conversation from different starting points and with different backgrounds. There are no dumb questions. +- Take space and give space. We strive to create an equitable environment in which all are welcome and able to participate. We hope individuals feel comfortable voicing their opinions and providing contributions and will do our best to recognize and make space for individuals who may be struggling to find space here. Likewise, we expect individuals to recognize when they are taking up significant space and take a step back to allow room for others. +- Be respectful. +- Default to positive. Assume others' contributions are legitimate and valuable and that they are made with good intention. + +## Acknowledgements +This Community Guidelines was adapted from the [United States Digital Service](https://usds.gov) [Justice40](https://thejustice40.com) open source [repository](https://github.com/usds/justice40-tool). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d80c97e..f87c3a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,58 +1,39 @@ -# Contributing - -Feedback and contributions are very welcome! - -Here's help on how to make contributions, divided into the following sections: - -- [general information](#general-information), -- [vulnerability reporting](#vulnerability-reporting-security-issues), -- [code changes](#code-changes), - -## General information -For specific proposals, please provide them as [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls) or [issues](https://github.com/coreinfrastructure/best-practices-badge/issues) via our [GitHub site](https://github.com/davidbrownell/FileBackup). - -The [DEVELOPMENT.md](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) file explains how to install the program locally (highly recommended if you're going to make code changes). It also provides a quick start guide. - -### Pull requests and different branches recommended -Pull requests are preferred, since they are specific. For more about how to create a pull request, see https://help.github.com/articles/using-pull-requests/. - -We recommend creating different branches for different (logical) changes, and creating a pull request when you're done into the main branch. See the GitHub documentation on [creating branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) and [using pull requests](https://help.github.com/articles/using-pull-requests/). - -### How we handle proposals -We use GitHub to track proposed changes via its [issue tracker](https://github.com/coreinfrastructure/best-practices-badge/issues) and [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls). Specific changes are proposed using those mechanisms. Issues are assigned to an individual, who works and then marks it complete. If there are questions or objections, the conversation are of that issue or pull request is used to resolve it. - -### We are proactive -In general we try to be proactive to detect and eliminate mistakes and vulnerabilities as soon as possible, and to reduce their impact when they do happen. We use a defensive design and coding style to reduce the likelihood of mistakes, a variety of tools that try to detect mistakes early, and an automatic test suite with significant coverage. We also release the software as open source software so others can review it. - -Since early detection and impact reduction can never be perfect, we also try to detect and repair problems during deployment as quickly as possible. This is especially true for security issues; see our [security information](#vulnerability-reporting-security-issues) for more. - -## Vulnerability reporting (security issues) -Please privately report vulnerabilities you find so we can fix them! - -See [SECURITY.md](https://github.com/davidbrownell/FileBackup/blob/main/SECURITY.md) for information on how to privately report vulnerabilities. - -## Code changes -To make changes to the "FileBackup" web application that implements the criteria, you may find [DEVELOPMENT.md](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) helpful. - -The code should strive to be DRY (don't repeat yourself), clear, and obviously correct. Some technical debt is inevitable, just don't bankrupt us with it. Improved refactorizations are welcome. - -### Automated tests -When adding or changing functionality, please include new tests for them as part of your contribution. - -We require the code to have at a minimum statement coverage (that is measured and enforced during the [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) process); please ensure your contributions do not lower the coverage below that minimum. - -We encourage tests to be created first, run to ensure they fail, and then add code to implement the test (aka test driven development). However, each git commit should have both the test and improvement in the same commit, because 'git bisect' will then work well. - -### How to check proposed changes before submitting them -See [DEVELOPMENT.md](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) for information on how to run tests on your local machine before submitting them as a pull request. - -### Git commit messages -When writing git commit messages, try to follow the guidelines in [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/): - -1. Separate subject from body with a blank line -2. Limit the subject line to 50 characters. (We're flexible on this, but do limit it to 72 characters or less.) -3. Capitalize the subject line -4. Do not end the subject line with a period -5. Use the imperative mood in the subject line (command form) -6. Wrap the body at 72 characters ("fmt -w 72") -7. Use the body to explain what and why vs. how (git tracks how it was changed in detail, don't repeat that) +# Contribution Guidelines + +## Contributor Code of Conduct +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity, expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. + +Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. + +[Project maintainers](MAINTAINERS.md) have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the [project maintainers](MAINTAINERS.md). + +## General information +For specific proposals, please provide them as [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls) or [issues](https://github.com/coreinfrastructure/best-practices-badge/issues) via our [GitHub site](https://github.com/davidbrownell/FileBackup). + +The [DEVELOPMENT.md](DEVELOPMENT.md) file explains how to install the program locally (highly recommended if you're going to make code changes). It also provides information useful for making changes and validating them locally before submitting a pull request. + +### Pull requests and different branches recommended +Pull requests are preferred, since they are specific. For more about how to create a pull request, see https://help.github.com/articles/using-pull-requests/. + +We recommend creating different branches for different (logical) changes, and creating a pull request into the `main` branch when you're done. See the GitHub documentation on [creating branches](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) and [using pull requests](https://help.github.com/articles/using-pull-requests/). + +### How we handle proposals +We use GitHub to track proposed changes via its [issue tracker](https://github.com/coreinfrastructure/best-practices-badge/issues) and [pull requests](https://github.com/coreinfrastructure/best-practices-badge/pulls). Specific changes are proposed using those mechanisms. Issues are assigned to an individual, who works and then marks it complete. If there are questions or objections, the conversation of that issue or pull request is used to resolve it. + +### We are proactive +In general we try to be proactive to detect and eliminate mistakes and vulnerabilities as soon as possible, and to reduce their impact when they do happen. We use a defensive design and coding style to reduce the likelihood of mistakes, a variety of tools that try to detect mistakes early, and an automatic test suite with significant coverage. We also release the software as open source software so others can review it. + +Since early detection and impact reduction can never be perfect, we also try to detect and repair problems during deployment as quickly as possible. This is especially true for security issues; see our [security information](#vulnerability-reporting-security-issues) for more information. + +## Vulnerability reporting (security issues) +Please privately report vulnerabilities you find so we can fix them! + +See [SECURITY.md](SECURITY.md) for information on how to privately report vulnerabilities. + +## Acknowledgements + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index dc753a8..aacceaa 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,33 +1,84 @@ -## Local Development - -Follow these steps to prepare the repository for local development activities. - -1) Clone this repository -2) Bootstrap the local repository by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS |

Standard:
`Bootstrap.sh`

Standard + packaging:
`Bootstrap.sh --package`

| - | Windows |

Standard:
`Bootstrap.cmd`

Standard + packaging:
`Bootstrap.cmd --package`

| -3) Activate the development environment by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS | `. ./Activate.sh` | - | Windows | `Activate.cmd` | -4) Invoke `Build.py` - | Command | Description | Example | Notes | - | --- | --- | --- | --- | - | `black` | Validates that the source code is formatted by [black](https://github.com/psf/black). |

Validation:
`python Build.py black`

Perform formatting:
`python Build.py black --format`

| | - | `pylint` | Validates the source code using [pylint](https://github.com/pylint-dev/pylint). | `python Build.py pylint` | | - | `pytest` | Runs automated tests using [pytest](https://docs.pytest.org/). |

Without Code Coverage:
`python Build.py pytest`

With Code Coverage:
`python Build.py pytest --code-coverage`

| | - | `update_version` | Updates the [semantic version](https://semver.org/) of the package based on git commits using [AutoGitSemVer](https://github.com/davidbrownell/AutoGitSemVer). | `python Build.py update_version` | | - | `package` | Creates a Python wheel package for distribution; outputs to the `/dist` directory. | `python Build.py package` | Requires `--package` when bootstrapping in step #2. | - | `publish` | Publishes a Python wheel package to [PyPi](https://pypi.org/). |

https://test.pypi.org:
`python Build.py publish`

https://pypi.org:
`python Build.py publish --production`

| Requires `--package` when bootstrapping in step #2. | - | `build_binary` | Builds an executable for your package that can be run on machines without a python installation; outputs to the `/build` directory. | `python Build.py build_binary` | Requires `--package` when bootstrapping in step #2. | - | `create_docker_image` | Creates a [Docker](https://www.docker.com/) image based on the current development environment. This supports the "Reusable" aspect of [FAIR principles](https://www.go-fair.org/fair-principles/) by creating a snapshot of the repository and all of its dependencies as they exist in a single moment in time. | `python Build.py create_docker_image` | Requires docker. | - - -5) [Optional] Deactivate the development environment by running... - | Operating System | Command | - | --- | --- | - | Linux / MacOS | `. ./Deactivate.sh` | - | Windows | `Deactivate.cmd` | +# Local Development + +## Enlistment +Enlistment in this repository involves these steps. + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StepCommand LineDescription
1. Clone the repository locallygit clone https://github.com/davidbrownell/FileBackuphttps://git-scm.com/docs/git-clone
2. Bootstrap the environment + + + + + + + + + +
Linux / MacOS./Bootstrap.sh [--python-version <python version>]
WindowsBootstrap.cmd [--python-version <python version>]
+
Prepares the repository for local development by enlisting in all dependencies.
3. Activate the environment + + + + + + + + + +
Linux / MacOS. ./Activate.sh
WindowsActivate.cmd
+
+

Activates the terminal for development. Each new terminal window must be activated.

+

Activate.sh/.cmd is actually a shortcut to the most recently bootstrapped version of python (e.g. Activate3.11.sh/.cmd). With this functionality, it is possible to support multiple python versions in the same repository and activate each in a terminal using the python-specific activation script.

+
4. [Optional] Deactivate the environment + + + + + + + + + +
Linux / MacOS. ./Deactivate.sh
WindowsDeactivate.cmd
+
+ Deactivates the terminal environment. Deactivating is optional, as the terminal window itself may be closed when development activities are complete. +
+ +## Development Activities +Each of these activities can be invoked from an activated terminal on your local machine. + +| Activity | Command Line | Description | Invoked by Continuous Integration | +| --- | --- | --- | :-: | +| Code Formatting | `python Build.py black [--format]` | Format source code using [black](https://github.com/psf/black) based on settings in `pyproject.toml`. | :white_check_mark: | +| Static Code Analysis | `python Build.py pylint` | Validate source code using [pylint](https://github.com/pylint-dev/pylint) based on settings in `pyproject.toml`. | :white_check_mark: | +| Automated Testing | `python Build.py pytest [--code-coverage]` | Run automated tests using [pytest](https://docs.pytest.org/) and (optionally) extract code coverage information using [coverage](https://coverage.readthedocs.io/) based on settings in `pyproject.toml`. | :white_check_mark: | +| Semantic Version Generation | `python Build.py update_version` | Generate a new [Semantic Version](https://semver.org) based on git commits using [AutoGitSemVer](https://github.com/davidbrownell/AutoGitSemVer). Version information is stored in `/src/FileBackup/__init__.py`. | :white_check_mark: | +| Python Package Creation |

python Build.py package

Requires that the repository was bootstrapped with the --package flag. | Create a python package using [setuptools](https://github.com/pypa/setuptools) based on settings in `pyproject.toml`. | :white_check_mark: | +| Python Package Publishing |

python Build.py publish

Requires that the repository was bootstrapped with the --package flag. | Publish a python package to [PyPi](https://pypi.org). | :white_check_mark: | +| Build Binaries | `python Build.py build_binaries` | Create a python binary for your current operating system using [cx_Freeze](https://cx-freeze.readthedocs.io/) based on settings in `src/BuildBinary.py`. | :white_check_mark: | +| Development Docker Image | `python Build.py create_docker_image` | Create a [docker](https://docker.com) image for a bootstrapped development environment. This functionality is useful when adhering to the [FAIR principles for research software](https://doi.org/10.1038/s41597-022-01710-x) by supporting the creation of a development environment and its dependencies as they existed at the moment when the image was created. | :white_check_mark: | diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..2a767e0 --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,2 @@ +# Governance +This project is governed by our [Code of Conduct](CODE_OF_CONDUCT.md) and [Contribution Guidelines](CONTRIBUTING.md). diff --git a/LICENSE.txt b/LICENSE.txt index 1f8aac0..cae680c 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,21 @@ -MIT LICENSE - -Copyright (c) 2024 David Brownell - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT LICENSE + +Copyright (c) 2024 David Brownell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/MAINTAINERS.md b/MAINTAINERS.md new file mode 100644 index 0000000..5f5c734 --- /dev/null +++ b/MAINTAINERS.md @@ -0,0 +1,14 @@ +# Maintainers + +This page lists all active maintainers of this repository. If you were a maintainer and would like to add your name to the Emeritus list, please send us a pull request. + +See [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) for general contribution guidelines. + +## Current Maintainers +| Maintainer | GitHub ID | Affiliation | +| --- | --- | --- | +| David Brownell | davidbrownell | | + +## Emeritus +| Maintainer | GitHub ID | Affiliation | +| --- | --- | --- | diff --git a/README.md b/README.md index 831cea1..0171342 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,76 @@ -# FileBackup - - -[![CI](https://github.com/davidbrownell/FileBackup/actions/workflows/standard.yaml/badge.svg?event=push)](https://github.com/davidbrownell/FileBackup/actions/workflows/standard.yaml) -[![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/davidbrownell/f15146b1b8fdc0a5d45ac0eb786a84f7/raw/FileBackup_coverage.json)](https://github.com/davidbrownell/FileBackup/actions) -[![License](https://img.shields.io/github/license/davidbrownell/FileBackup?color=dark-green)](https://github.com/davidbrownell/FileBackup/blob/master/LICENSE.txt) -[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/davidbrownell/FileBackup?color=dark-green)](https://github.com/davidbrownell/FileBackup/commits/main/) -[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/FileBackup?color=dark-green)](https://pypi.org/project/filebackup/) -[![PyPI - Version](https://img.shields.io/pypi/v/FileBackup?color=dark-green)](https://pypi.org/project/filebackup/) -[![PyPI - Downloads](https://img.shields.io/pypi/dm/FileBackup)](https://pypistats.org/packages/filebackup) -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9069/badge)](https://www.bestpractices.dev/projects/9069) - - - -Tool for creating and restoring file system backups. - - -## Contents -- [Overview](#overview) -- [Installation](#installation) -- [Contributing](#contributing) -- [Local Development](#local-development) -- [Vulnerability Reporting](#vulnerability-reporting-security-issues) -- [License](#license) - - -## Overview - -TODO: Complete this section - -### How to use FileBackup - -TODO: Complete this section - - -## Installation - -FileBackup can be installed via one of these methods: - -- [Installation via Executable](#installation-via-executable) -- [Installation via pip](#installation-via-pip) - -### Installation via Executable - -Download an executable for Linux, MacOS, or Windows to use the functionality provided by this repository without a dependency on [Python](https://www.python.org). - -1. Download the archive for the latest release [here](https://github.com/davidbrownell/FileBackup/releases/latest); the files will begin with `exe.` and contain the name of your operating system. -2. Decompress the archive - - -#### Verifying Signed Executables - -Executables are signed and validated using [Minisign](https://jedisct1.github.io/minisign/). - -The public key for executables in this repository is `RWTO8gifpEKQhwiguxsldM47Php1GeTs0foueIpaLPp0xSy0N5FBn/70`. - -To verify that the executable is valid, download the corresponding `.minisig` file [here](https://github.com/davidbrownell/FileBackup/releases/latest) and run this command, replacing `` with the name of your file. - -`docker run -i --rm -v .:/host jedisct1/minisign -V -P RWTO8gifpEKQhwiguxsldM47Php1GeTs0foueIpaLPp0xSy0N5FBn/70 -m /host/` - -Instructions for installing [docker](https://docker.com) are available at https://docs.docker.com/engine/install/. - - - -### Installation via pip - -Install the FileBackup package via [pip](https://pip.pypa.io/en/stable/) (Package Installer for Python) to use it with your python code. - -`pip install FileBackup` - -## Contributing -See [CONTRIBUTING.md](https://github.com/davidbrownell/FileBackup/blob/main/CONTRIBUTING.md) for information on contributing to FileBackup. - -## Local Development - -See [DEVELOPMENT.md](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) for information on developing or testing FileBackup on your local Linux, MacOS, or Windows machine. - - -## Vulnerability Reporting (Security Issues) -Please privately report vulnerabilities you find so we can fix them! - -See [SECURITY.md](https://github.com/davidbrownell/FileBackup/blob/main/SECURITY.md) for information on how to privately report vulnerabilities. - -## License - -FileBackup is licensed under the MIT license. +# FileBackup + + +[![License](https://img.shields.io/github/license/davidbrownell/FileBackup?color=dark-green)](https://github.com/davidbrownell/FileBackup/blob/master/LICENSE.txt) +[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/davidbrownell/FileBackup?color=dark-green)](https://github.com/davidbrownell/FileBackup/commits/main/) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/FileBackup?color=dark-green)](https://pypi.org/project/FileBackup/) +[![PyPI - Version](https://img.shields.io/pypi/v/FileBackup?color=dark-green)](https://pypi.org/project/FileBackup/) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/FileBackup)](https://pypistats.org/packages/FileBackup) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9069/badge)](https://www.bestpractices.dev/projects/9069) +[![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/davidbrownell/f15146b1b8fdc0a5d45ac0eb786a84f7/raw/FileBackup_coverage.json)](https://github.com/davidbrownell/FileBackup/actions) + + +Tool for creating and restoring file system backups. + + +## Contents +- [Overview](#overview) +- [Installation](#installation) +- [Development](#development) +- [Additional Information](#additional-information) +- [License](#license) + + +## Overview +TODO: Complete this section + +### How to use FileBackup +TODO: Complete this section + + +## Installation +FileBackup can be installed via one of these methods: + +- [Installation via Executable](#installation-via-executable) +- [Installation via pip](#installation-via-pip) + +### Installation via Executable +Download an executable for Linux, MacOS, or Windows to the the functionality provided by this repository without a dependency on python. + +1. Download the archive for the latest release [here](https://github.com/davidbrownell/FileBackup/releases/latest). The filename will begin with `exe.` and contain the name of your operating system. +2. Decompress the archive. + +#### Verifying Signed Executables +Executables are signed and validated using [Minisign](https://jedisct1.github.io/minisign/). The public key used to verify the signature of the executable is `RWRklbWaX9KiNb8bzXIMVsGOyjIFbIlaY+ZSr8TBdcc5vcNLl1OKpqXE`. + +To verify that the executable is valid, download the corresponding `.minisig` file [here](https://github.com/davidbrownell/FileBackup/releases/latest) and run this command, replacing `` with the name of the file to be verified: + +`docker run -i --rm -v .:/host jedisct1/minisign -V -P RWRklbWaX9KiNb8bzXIMVsGOyjIFbIlaY+ZSr8TBdcc5vcNLl1OKpqXE -m /host/` + +Instructions for installing [docker](https://docker.com) are available at https://docs.docker.com/engine/install/. + +### Installation via pip +To install the FileBackup package via [pip](https://pip.pypa.io/en/stable/) (Python Installer for Python) for use with your python code: + +`pip install FileBackup` + + +## Development +Please visit [Contributing](https://github.com/davidbrownell/FileBackup/blob/main/CONTRIBUTING.md) and [Development](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) for information on contributing to this project. + + +## Additional Information +Additional information can be found at these locations. + +| Title | Document | Description | +| --- | --- | --- | +| Code of Conduct | [CODE_OF_CONDUCT.md](https://github.com/davidbrownell/FileBackup/blob/main/CODE_OF_CONDUCT.md) | Information about the the norms, rules, and responsibilities we adhere to when participating in this open source community. | +| Contributing | [CONTRIBUTING.md](https://github.com/davidbrownell/FileBackup/blob/main/CONTRIBUTING.md) | Information about contributing code changes to this project. | +| Development | [DEVELOPMENT.md](https://github.com/davidbrownell/FileBackup/blob/main/DEVELOPMENT.md) | Information about development activities involved in making changes to this project. | +| Governance | [GOVERNANCE.md](https://github.com/davidbrownell/FileBackup/blob/main/GOVERNANCE.md) | Information about how this project is governed. | +| Maintainers | [MAINTAINERS.md](https://github.com/davidbrownell/FileBackup/blob/main/MAINTAINERS.md) | Information about individuals who maintain this project. | +| Security | [SECURITY.md](https://github.com/davidbrownell/FileBackup/blob/main/SECURITY.md) | Information about how to privately report security issues associated with this project. | + +## License + +FileBackup is licensed under the MIT license. diff --git a/SECURITY.md b/SECURITY.md index 1466503..87fc639 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,9 +1,9 @@ -# Security - -If you find a significant vulnerability, or evidence of one, please report it privately. - -We prefer that you use the [GitHub mechanism for privately reporting a vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). Under the [main repository's security tab](https://github.com/davidbrownell/FileBackup/security), in the left sidebar, under "Reporting", click Advisories, then click "Report a vulnerability" to open the advisory form. - -We will gladly give credit to anyone who reports a vulnerability so that we can fix it. If you want to remain anonymous or pseudonymous instead, please let us know that; we will gladly respect your wishes. - -We gladly welcome patches to fix such vulnerabilities! See [CONTRIBUTING.md](https://github.com/davidbrownell/FileBackup/blob/main/CONTRIBUTING.md) for information about contributions. +# Security + +If you find a significant vulnerability, or evidence of one, please report it privately. + +We prefer that you use the [GitHub mechanism for privately reporting a vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). Under the [main repository's security tab](https://github.com/davidbrownell/FileBackup/security), in the left sidebar, under "Reporting", click "Advisories", click the "New draft security advisory" button to open the advisory form. + +We will gladly give credit to anyone who reports a vulnerability so that we can fix it. If you want to remain anonymous or pseudonymous instead, please let us know that; we will gladly respect your wishes. + +We gladly welcome patches to fix such vulnerabilities! See [CONTRIBUTING.md](CONTRIBUTING.md) for information about contributions. diff --git a/minisign_key.pub b/minisign_key.pub new file mode 100644 index 0000000..53a4830 --- /dev/null +++ b/minisign_key.pub @@ -0,0 +1,2 @@ +untrusted comment: minisign public key 35A2D25F9AB59564 +RWRklbWaX9KiNb8bzXIMVsGOyjIFbIlaY+ZSr8TBdcc5vcNLl1OKpqXE diff --git a/pyproject.toml b/pyproject.toml index 5c49f03..29986b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,197 +1,192 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 David Brownell -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ - -[build-system] -requires = ["setuptools >= 63.0"] -build-backend = "setuptools.build_meta" - -# ---------------------------------------------------------------------- -# | -# | Project -# | -# ---------------------------------------------------------------------- -[project] -name = "FileBackup" -description = "Tool for creating and restoring file system backups." - -license = { text = "MIT" } - -authors = [ - { name = "David Brownell", email = "github@DavidBrownell.com" }, -] - -keywords = [ - "backup", - "mirror", - "offsite", - "restore", -] - -# https://pypi.org/classifiers/ -classifiers = [ - "Development Status :: 4 - Beta", # TODO - "Environment :: Console", - "Intended Audience :: Developers", - "Intended Audience :: End Users/Desktop", - "Intended Audience :: System Administrators", - "License :: OSI Approved :: MIT License", - "Natural Language :: English", - "Operating System :: MacOS", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: System :: Archiving :: Backup", - "Topic :: System :: Archiving :: Mirroring", - "Topic :: System :: Systems Administration", - "Topic :: Utilities", -] - -dependencies = [ - "dbrownell_Common", - "paramiko ~= 3.4", - "typer ~= 0.9" -] - -dynamic = [ - "version", -] - -readme = "README.md" - -[project.optional-dependencies] -dev = [ - "dbrownell_DevTools", -] - -package = [ - "build ~= 1.2", - "cx_Freeze ~= 6.15", - "twine ~= 5.1", -] - -[project.urls] -Homepage = "https://github.com/davidbrownell/FileBackup" -Documentation = "https://github.com/davidbrownell/FileBackup" -Repository = "https://github.com/davidbrownell/FileBackup" - -[project.scripts] -FileBackup = "FileBackup.CommandLine:EntryPoint.app" - -# ---------------------------------------------------------------------- -# | -# | black -# | -# ---------------------------------------------------------------------- -[tool.black] -line-length = 100 - -# ---------------------------------------------------------------------- -# | -# | coverage -# | -# ---------------------------------------------------------------------- -[tool.coverage.run] -omit = [ - "*/Impl/*", -] - -# ---------------------------------------------------------------------- -# | -# | pylint -# | -# ---------------------------------------------------------------------- -[tool.pylint.basic] -class-const-naming-style = "any" -function-naming-style = "PascalCase" -good-names = [ - "i", - "j", - "k", - "ex", - "Run", - "_", - "dm", # added - "f", # added -] -method-naming-style = "any" -module-naming-style = "PascalCase" - -[tool.pylint.design] -max-args = 10 -max-parents = 15 - -[tool.pylint.main] -ignore-paths = [ - # Note that the pylint vscode extension has trouble with wrapping these patterns in quotes - # (which is required to parse the file correctly). Because of this, each pattern must be - # converted to a glob pattern and specified in the pylint vscode settings as well. - "^.+?Tests/.*$", -] - -[tool.pylint."messages control"] -disable = [ - "raw-checker-failed", - "bad-inline-option", - "locally-disabled", - "file-ignored", - "suppressed-message", - "useless-suppression", - "deprecated-pragma", - "use-symbolic-message-instead", - "assignment-from-no-return", # added - "broad-except", # added - "broad-exception-raised", # added - "cell-var-from-loop", # added - "consider-using-f-string", # added - "import-outside-toplevel", # added - "line-too-long", # added - "missing-function-docstring", # added - "subprocess-run-check", # added - "super-with-arguments", # added - "too-few-public-methods", # added - "unnecessary-lambda-assignment", # added - "unspecified-encoding", # added -] - -# ---------------------------------------------------------------------- -# | -# | pyright -# | -# ---------------------------------------------------------------------- -[tool.pyright] -exclude = [ - "**/*Tests/*", - "**/Generated/*", -] - -reportMissingImports = true -reportMissingTypeStubs = false - -# ---------------------------------------------------------------------- -# | -# | pytest -# | -# ---------------------------------------------------------------------- -[tool.pytest.ini_options] -python_files = [ - "**/*Test.py", -] - -# ---------------------------------------------------------------------- -# | -# | setuptools -# | -# ---------------------------------------------------------------------- -[tool.setuptools.dynamic] -version = { attr = "FileBackup.__version__" } - -[tool.setuptools.packages.find] -where = ["src"] +# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ + +[build-system] +requires = ["setuptools >= 63.0"] +build-backend = "setuptools.build_meta" + +# ---------------------------------------------------------------------- +# | +# | Project +# | +# ---------------------------------------------------------------------- +[project] +name = "FileBackup" +description = "Tool for creating and restoring file system backups." + +license = { text = "MIT" } + +authors = [ + { name = "David Brownell", email = "github@DavidBrownell.com" }, +] + +keywords = [ + "backup", + "mirror", + "offsite", + "restore", +] + +# https://pypi.org/classifiers/ +classifiers = [ + "Development Status :: 4 - Beta", # TODO + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: System :: Archiving :: Backup", + "Topic :: System :: Archiving :: Mirroring", + "Topic :: System :: Systems Administration", + "Topic :: Utilities", +] + +dependencies = [ + "dbrownell_Common", + "paramiko ~= 3.4", + "typer ~= 0.9" +] + +dynamic = [ + "version", +] + +readme = "README.md" + +[project.optional-dependencies] +dev = [ + "dbrownell_DevTools", +] + +package = [ + "build ~= 1.2", + "cx_Freeze ~= 6.15", + "twine ~= 5.1", +] + +[project.urls] +Homepage = "https://github.com/davidbrownell/FileBackup" +Documentation = "https://github.com/davidbrownell/FileBackup" +Repository = "https://github.com/davidbrownell/FileBackup" + + +[project.scripts] +FileBackup = "FileBackup.CommandLine:EntryPoint.app" + +# ---------------------------------------------------------------------- +# | +# | black +# | +# ---------------------------------------------------------------------- +[tool.black] +line-length = 100 + +# ---------------------------------------------------------------------- +# | +# | coverage +# | +# ---------------------------------------------------------------------- +[tool.coverage.run] +omit = [ + "*/Impl/*", +] + +# ---------------------------------------------------------------------- +# | +# | pylint +# | +# ---------------------------------------------------------------------- +[tool.pylint.basic] +class-const-naming-style = "any" +function-naming-style = "PascalCase" +good-names = [ + "i", + "j", + "k", + "ex", + "Run", + "_", + "dm", # added + "f", # added +] +method-naming-style = "any" +module-naming-style = "PascalCase" + +[tool.pylint.design] +max-args = 10 +max-parents = 15 + +[tool.pylint.main] +ignore-paths = [ + # Note that the pylint vscode extension has trouble with wrapping these patterns in quotes + # (which is required to parse the file correctly). Because of this, each pattern must be + # converted to a glob pattern and specified in the pylint vscode settings as well. + "^.+?Tests/.*$", +] + +[tool.pylint."messages control"] +disable = [ + "raw-checker-failed", + "bad-inline-option", + "locally-disabled", + "file-ignored", + "suppressed-message", + "useless-suppression", + "deprecated-pragma", + "use-symbolic-message-instead", + "assignment-from-no-return", # added + "broad-except", # added + "broad-exception-raised", # added + "cell-var-from-loop", # added + "consider-using-f-string", # added + "import-outside-toplevel", # added + "line-too-long", # added + "missing-function-docstring", # added + "subprocess-run-check", # added + "super-with-arguments", # added + "too-few-public-methods", # added + "unnecessary-lambda-assignment", # added + "unspecified-encoding", # added +] + +# ---------------------------------------------------------------------- +# | +# | pyright +# | +# ---------------------------------------------------------------------- +[tool.pyright] +exclude = [ + "**/*Tests/*", + "**/Generated/*", +] + +reportMissingImports = true +reportMissingTypeStubs = false + +# ---------------------------------------------------------------------- +# | +# | pytest +# | +# ---------------------------------------------------------------------- +[tool.pytest.ini_options] +python_files = [ + "**/*Test.py", +] + +# ---------------------------------------------------------------------- +# | +# | setuptools +# | +# ---------------------------------------------------------------------- +[tool.setuptools.dynamic] +version = { attr = "FileBackup.__version__" } + +[tool.setuptools.packages.find] +where = ["src"] diff --git a/src/AutoGitSemVer.yaml b/src/AutoGitSemVer.yaml index fbe26bc..01bc4bc 100644 --- a/src/AutoGitSemVer.yaml +++ b/src/AutoGitSemVer.yaml @@ -1,6 +1,6 @@ -# This file is used by AutoGitSemVer to configure the semantic version of the FileBackup package. -# It indicates that AutoGitSemVer should only look at changes in this directory, its descendants, and files specified in -# additional_dependencies when calculating the semantic version for the package. -additional_dependencies: - - "../pyproject.toml" - - "../README.md" +# This file is used by AutoGitSemVer to configure the semantic version of the FileBackup package. +# It indicates that AutoGitSemVer should only look at changes in this directory, its descendants, and files specified in +# additional_dependencies when calculating the semantic version for the package. +additional_dependencies: + - "../pyproject.toml" + - "../README.md" diff --git a/src/BuildBinary.py b/src/BuildBinary.py index 8ccd375..f34c1cf 100644 --- a/src/BuildBinary.py +++ b/src/BuildBinary.py @@ -1,104 +1,93 @@ -# ---------------------------------------------------------------------- -# | -# | Copyright (c) 2024 David Brownell -# | Distributed under the MIT License. -# | -# ---------------------------------------------------------------------- -"""Builds the binary for this project.""" - -import datetime -import importlib -import textwrap - -from functools import cache -from pathlib import Path - -from cx_Freeze import setup, Executable -from dbrownell_Common import PathEx - - -# ---------------------------------------------------------------------- -@cache -def _GetName() -> str: - return "FileBackup" - - -# ---------------------------------------------------------------------- -@cache -def _GetVersionAndDocstring() -> tuple[str, str]: - mod = importlib.import_module(_GetName()) - return mod.__version__, mod.__doc__ or "" - - -# ---------------------------------------------------------------------- -@cache -def _GetEntryPoint() -> Path: - return PathEx.EnsureFile(Path(__file__).parent / _GetName() / "CommandLine" / "EntryPoint.py") - - -# ---------------------------------------------------------------------- -@cache -def _GetCopyright() -> str: - initial_year = 2024 - current_year = datetime.datetime.now().year - - if current_year == initial_year: - year_suffix = "" - elif current_year // 100 != initial_year // 100: - year_suffix = str(current_year) - else: - year_suffix = "-{}".format(current_year % 100) - - return textwrap.dedent( - f"""\ - Copyright (c) {initial_year}{year_suffix} David Brownell - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - """, - ) - - -# ---------------------------------------------------------------------- -setup( - name=_GetName(), - version=_GetVersionAndDocstring()[0], - description=_GetVersionAndDocstring()[1], - executables=[ - Executable( - _GetEntryPoint(), - base="console", - copyright=_GetCopyright(), - # icon=, - target_name=_GetName(), - # trademarks=, - ), - ], - options={ - "build_exe": { - "excludes": [ - "tcl", - "tkinter", - ], - "no_compress": False, - "optimize": 0, - # "packages": [], - # "include_files": [], - }, - }, -) +"""Builds the binary for this project.""" + +import datetime +import importlib +import re + +from functools import cache +from pathlib import Path + +from cx_Freeze import setup, Executable +from dbrownell_Common import PathEx + + +# ---------------------------------------------------------------------- +@cache +def _GetName() -> str: + return "FileBackup" + + +# ---------------------------------------------------------------------- +@cache +def _GetVersionAndDocstring() -> tuple[str, str]: + mod = importlib.import_module(_GetName()) + return mod.__version__, mod.__doc__ or "" + + +# ---------------------------------------------------------------------- +@cache +def _GetEntryPoint() -> Path: + return PathEx.EnsureFile(Path(__file__).parent / _GetName() / "CommandLine" / "EntryPoint.py") + + +# ---------------------------------------------------------------------- +@cache +def _GetCopyright() -> str: + match = re.search( + r"""(?# + Copyright )Copyright(?# + Mark [Optional] )(?P\s+\([cC]\))?(?# + Year )\s+(?P\d{4})(?# + Year Range [Optional] )(?:\s*-\s*\d{2,4})?(?# + Suffix )(?P.+)(?# + End of line )$(?# + )""", + PathEx.EnsureFile(Path(__file__).parent.parent / "LICENSE.txt").read_text(), + flags=re.MULTILINE, + ) + + current_year = datetime.datetime.now().year + + if not match: + return f"Copyright {current_year} David Brownell" + + initial_year = int(match.group("year")) + + if current_year == initial_year: + year_suffix = "" + elif current_year // 100 != initial_year // 100: + year_suffix = f"-{current_year}" + else: + year_suffix = f"-{current_year % 100}" + + return f"Copyright{match.group('mark')} {initial_year}{year_suffix} David Brownell" + + +# ---------------------------------------------------------------------- +setup( + name=_GetName(), + version=_GetVersionAndDocstring()[0], + description=_GetVersionAndDocstring()[1], + executables=[ + Executable( + _GetEntryPoint(), + base="console", + copyright=_GetCopyright(), + # icon=, + target_name=_GetName(), + # trademarks=, + ), + ], + options={ + "build_exe": { + "excludes": [ + "tcl", + "tkinter", + ], + "no_compress": False, + "optimize": 0, + # "packages": [], + # "include_files": [], + }, + }, +)