codeplain 0.3.8__tar.gz → 0.3.10.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.github/workflows/e2e.yml +28 -1
- codeplain-0.3.10.dev1/.github/workflows/lint-powershell.yml +124 -0
- codeplain-0.3.10.dev1/.github/workflows/publish-dev-to-pypi.yml +135 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.github/workflows/publish-install-script.yml +17 -0
- codeplain-0.3.10.dev1/.github/workflows/publish-to-pypi.yml +117 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/CLAUDE.md +10 -6
- codeplain-0.3.10.dev1/CONTRIBUTING.md +137 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/PKG-INFO +36 -8
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/README.md +31 -3
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/concept_utils.py +6 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/docs/plain2code_cli.md +25 -23
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/docs/starting_a_plain_project_from_scratch.md +8 -2
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/run.sh +2 -2
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/run.sh +2 -2
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/run.sh +1 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/git_utils.py +0 -10
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/install/bash/install.sh +41 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/install/powershell/examples.ps1 +11 -5
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/install/powershell/install.ps1 +131 -19
- codeplain-0.3.10.dev1/install/powershell/walkthrough.ps1 +174 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/memory_management.py +2 -3
- codeplain-0.3.10.dev1/metadata_utils.py +46 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/module_renderer.py +9 -6
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/partial_rendering.py +35 -4
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code.py +37 -4
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_arguments.py +13 -19
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_cli.md +17 -19
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_console.py +3 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_exceptions.py +8 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_logger.py +37 -15
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_telemetry.py +17 -11
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain_file.py +18 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain_modules.py +264 -42
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/pyproject.toml +3 -3
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/prepare_repositories.py +8 -10
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/conformance_tests.py +48 -9
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/implementation_code_helpers.py +5 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/render_context.py +14 -4
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/render_utils.py +1 -2
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/requirements.txt +3 -3
- codeplain-0.3.10.dev1/system_config.py +148 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/e2e/test_hello_world_python.py +1 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/e2e/test_hello_world_python_windows.py +1 -1
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_arg_provenance.py +3 -3
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_cli_output.py +13 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_folder_path_resolution.py +12 -13
- codeplain-0.3.10.dev1/tests/test_headless_logging.py +177 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plain2code.py +1 -2
- codeplain-0.3.10.dev1/tests/test_plain_modules.py +794 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plainfileparser.py +41 -4
- codeplain-0.3.10.dev1/tests/test_prepare_repositories_layout.py +277 -0
- codeplain-0.3.10.dev1/tests/test_system_config.py +95 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_telemetry.py +31 -10
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/plain_module_render_choice_tui.py +25 -8
- codeplain-0.3.8/.github/workflows/publish-to-pypi.yml +0 -70
- codeplain-0.3.8/install/powershell/walkthrough.ps1 +0 -161
- codeplain-0.3.8/system_config.py +0 -68
- codeplain-0.3.8/tests/test_plain_modules.py +0 -343
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.claude/settings.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.flake8 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.github/dependabot.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.github/workflows/lint-and-test.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.github/workflows/nofity-slack-on-main-merge.yml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.gitignore +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.vscode/launch.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/.vscode/settings.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/LICENSE +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/change_detection.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/cli_output/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/cli_output/dry_run.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/cli_output/render_summary.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/cli_output/status.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/codeplain_REST_api.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/config/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/config/system_config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/diff_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/docs/generate_cli.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/event_bus.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/harness_tests/hello_world_test.go +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_golang/hello_world_golang.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/harness_tests/hello_world_display/test_hello_world.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_python/hello_world_python.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/config.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/e2e/hello_world.cy.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress/support/e2e.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/cypress.config.ts +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/package.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/harness_tests/hello_world_display/tsconfig.json +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/example_hello_world_react/hello_world_react.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/examples/run.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/file_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/install/bash/examples.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/install/bash/walkthrough.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_events.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_nodes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_read_config.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_state.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain2code_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/plain_spec.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/pytest.ini +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/analyze_specification_ambiguity.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/base_action.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/commit_conformance_tests_changes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/commit_implementation_code_changes.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/create_dist.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/exit_with_error.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/finish_functional_requirement.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/fix_conformance_test.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/fix_unit_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/prepare_testing_environment.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/refactor_code.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/render_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/render_functional_requirement.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/run_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/run_unit_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/actions/summarize_conformance_tests.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/code_renderer.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/render_types.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/state_machine_config.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/states.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/render_machine/triggers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/resources/codeplain_overview.png +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/resources/plain_example.png +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/standard_template_library/golang-console-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/standard_template_library/python-console-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/standard_template_library/typescript-react-app-boilerplate.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/standard_template_library/typescript-react-app-template.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_cypress.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_cypress.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_golang.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_golang.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_python.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_conformance_tests_python.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_flutter.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_flutter.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_golang.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_golang.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_python.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_python.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_react.ps1 +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/test_scripts/run_unittests_react.sh +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/conftest.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/acceptance_tests_warning/main_requiring_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/acceptance_tests_warning/required_with_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/circular_imports_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_import_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/diamond_imports_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/import_with_functionalities.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/imports_module_with_functionalities.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/imports/non_existent_import.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_code_var.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_implement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_leaf.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_middle.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_root.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/partial_rendering/pr_solo.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/add_new_task_modal_specification.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/duplicate_specification_heading.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/empty_functional_specs_section.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/invalid_specification_order.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/missing_non_functional_requirements.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/no_functional_specs_section.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/plain_source_with_absolute_link.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/plain_source_with_url_link.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/task_list_ui_specification.yaml +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/task_manager_with_reference_links.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfile/without_non_functional_requirement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_acceptance_tests.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_acceptance_tests_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_defined_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_defined_nondefined_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_definition.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_noconcepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_nonconcept.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_nondefined.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_redefinition.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_several_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/concept_validation_valid.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_base.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_missing.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_missing_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_nested.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_nested_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_l1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/exported_concepts_transitive_l2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/plain_file_parser_with_comments.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/plain_file_with_comments_indented.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/regular_plain_source.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_defs.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_example.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_l1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_l2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_missing.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_module.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_partial.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/required_concepts_partial_duplicate.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/topological_sort.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/plainfileparser/topological_sort_not_referenced.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/circular_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/circular_requires_sub.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/diamond_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/independent_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/non_existent_require.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_1.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_common.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/requires/normal_requires_main.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/sample_base64_image.txt +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/simple.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/block_level_include.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/code_variables.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/header.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/implement.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/implement_2.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/template_include.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/data/templates/test_hardest_problem.plain +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/e2e/Dockerfile +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/e2e/conftest.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_change_detection.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_console_log_styles.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_file_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_git_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_imports.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_log_file_name_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_logging_config_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_partial_rendering.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plain2code_state.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plain2code_utils.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plainfile.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_plainspec.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_requires.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_resolve_config_file.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_script_path_resolution.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_tui_usage.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tests/test_usage_summary.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/__init__.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/components.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/models.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/plain2code_tui.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/spinner.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/state_handlers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/styles.css +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/tui/widget_helpers.py +0 -0
- {codeplain-0.3.8 → codeplain-0.3.10.dev1}/usage_summary.py +0 -0
|
@@ -59,4 +59,31 @@ jobs:
|
|
|
59
59
|
- name: Run E2E tests
|
|
60
60
|
env:
|
|
61
61
|
CODEPLAIN_API_KEY: ${{ secrets.CODEPLAIN_API_KEY }}
|
|
62
|
-
run: pytest tests/e2e/ -v --tb=short
|
|
62
|
+
run: pytest tests/e2e/ -v --tb=short
|
|
63
|
+
|
|
64
|
+
notify-on-failure:
|
|
65
|
+
name: Notify Slack on failure
|
|
66
|
+
needs: [e2e-linux, e2e-windows]
|
|
67
|
+
if: failure()
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
env:
|
|
70
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_E2E_WEBHOOK_URL }}
|
|
71
|
+
steps:
|
|
72
|
+
- name: Determine failed platforms
|
|
73
|
+
id: platforms
|
|
74
|
+
run: |
|
|
75
|
+
failed=""
|
|
76
|
+
[ "${{ needs.e2e-linux.result }}" = "failure" ] && failed="Linux"
|
|
77
|
+
if [ "${{ needs.e2e-windows.result }}" = "failure" ]; then
|
|
78
|
+
[ -n "$failed" ] && failed="$failed and Windows" || failed="Windows"
|
|
79
|
+
fi
|
|
80
|
+
echo "failed=$failed" >> "$GITHUB_OUTPUT"
|
|
81
|
+
|
|
82
|
+
- name: Send failure notification to Slack
|
|
83
|
+
if: ${{ env.SLACK_WEBHOOK_URL != '' }}
|
|
84
|
+
uses: slackapi/slack-github-action@v1.24.0
|
|
85
|
+
with:
|
|
86
|
+
payload: |
|
|
87
|
+
{
|
|
88
|
+
"text": ${{ toJSON(format('[Codeplain Client] E2E tests FAILED on {0}. See <{1}/{2}/actions/runs/{3}|the run log>.', steps.platforms.outputs.failed, github.server_url, github.repository, github.run_id)) }}
|
|
89
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
name: PowerShell Install Scripts
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
paths:
|
|
6
|
+
- 'install/powershell/*.ps1'
|
|
7
|
+
- '.github/workflows/lint-powershell.yml'
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- 'install/powershell/*.ps1'
|
|
11
|
+
- '.github/workflows/lint-powershell.yml'
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
parse-windows-powershell-51:
|
|
16
|
+
name: Parse under Windows PowerShell 5.1
|
|
17
|
+
runs-on: windows-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
# The install scripts are fetched over HTTP and executed on stock Windows,
|
|
22
|
+
# where powershell.exe (5.1) is the default shell. 5.1 reads BOM-less files
|
|
23
|
+
# as ANSI (CP1252), so a non-ASCII glyph such as U+2713 decodes into a smart
|
|
24
|
+
# quote that silently terminates the enclosing string. The resulting parse
|
|
25
|
+
# errors point at unrelated lines far below the real cause, so parse every
|
|
26
|
+
# script with 5.1 explicitly rather than relying on PowerShell 7.
|
|
27
|
+
- name: Parse each script with 5.1
|
|
28
|
+
shell: powershell
|
|
29
|
+
run: |
|
|
30
|
+
$ErrorActionPreference = 'Stop'
|
|
31
|
+
Write-Host "PowerShell $($PSVersionTable.PSVersion) / ANSI codepage $([System.Text.Encoding]::Default.WebName)"
|
|
32
|
+
|
|
33
|
+
$failed = $false
|
|
34
|
+
Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
|
|
35
|
+
$errors = $null
|
|
36
|
+
[System.Management.Automation.Language.Parser]::ParseFile(
|
|
37
|
+
$_.FullName, [ref]$null, [ref]$errors) | Out-Null
|
|
38
|
+
|
|
39
|
+
if ($errors -and $errors.Count -gt 0) {
|
|
40
|
+
$failed = $true
|
|
41
|
+
Write-Host "FAIL $($_.Name): $($errors.Count) parse error(s)"
|
|
42
|
+
$errors | Sort-Object { $_.Extent.StartLineNumber } | ForEach-Object {
|
|
43
|
+
Write-Host " L$($_.Extent.StartLineNumber): $($_.Message)"
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
Write-Host "OK $($_.Name)"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if ($failed) { exit 1 }
|
|
51
|
+
|
|
52
|
+
# A BOM would fix file-based parsing but break `irm ... | iex`: PowerShell 5.1
|
|
53
|
+
# decodes an HTTP text/* body with no charset as ISO-8859-1, turning the BOM
|
|
54
|
+
# into literal "i>>?" text and failing with
|
|
55
|
+
# "The term 'i>>?$ErrorActionPreference' is not recognized".
|
|
56
|
+
# Keeping the sources pure ASCII is what makes both paths safe, so enforce it.
|
|
57
|
+
- name: Require pure ASCII and no BOM
|
|
58
|
+
shell: powershell
|
|
59
|
+
run: |
|
|
60
|
+
$ErrorActionPreference = 'Stop'
|
|
61
|
+
$failed = $false
|
|
62
|
+
|
|
63
|
+
Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
|
|
64
|
+
$fileBad = $false
|
|
65
|
+
$bytes = [System.IO.File]::ReadAllBytes($_.FullName)
|
|
66
|
+
|
|
67
|
+
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
|
|
68
|
+
$failed = $true
|
|
69
|
+
$fileBad = $true
|
|
70
|
+
Write-Host "FAIL $($_.Name): has a UTF-8 BOM (breaks 'irm | iex'); remove it"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Report line/column of any byte outside ASCII so the fix is obvious.
|
|
74
|
+
$text = [System.Text.Encoding]::UTF8.GetString($bytes)
|
|
75
|
+
$lineNo = 0
|
|
76
|
+
foreach ($line in ($text -split "`r?`n")) {
|
|
77
|
+
$lineNo++
|
|
78
|
+
for ($i = 0; $i -lt $line.Length; $i++) {
|
|
79
|
+
if ([int]$line[$i] -gt 127) {
|
|
80
|
+
$failed = $true
|
|
81
|
+
$fileBad = $true
|
|
82
|
+
$cp = "U+{0:X4}" -f [int]$line[$i]
|
|
83
|
+
Write-Host "FAIL $($_.Name) L${lineNo} C$($i + 1): non-ASCII $cp"
|
|
84
|
+
Write-Host " build it from its code point instead, e.g. `$CHECK = [char]0x2713"
|
|
85
|
+
break
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (-not $fileBad) { Write-Host "OK $($_.Name)" }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if ($failed) { exit 1 }
|
|
94
|
+
|
|
95
|
+
parse-powershell-7:
|
|
96
|
+
name: Parse under PowerShell 7
|
|
97
|
+
runs-on: windows-latest
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/checkout@v4
|
|
100
|
+
|
|
101
|
+
- name: Parse each script with 7
|
|
102
|
+
shell: pwsh
|
|
103
|
+
run: |
|
|
104
|
+
$ErrorActionPreference = 'Stop'
|
|
105
|
+
Write-Host "PowerShell $($PSVersionTable.PSVersion)"
|
|
106
|
+
|
|
107
|
+
$failed = $false
|
|
108
|
+
Get-ChildItem 'install/powershell' -Filter *.ps1 | Sort-Object Name | ForEach-Object {
|
|
109
|
+
$errors = $null
|
|
110
|
+
[System.Management.Automation.Language.Parser]::ParseFile(
|
|
111
|
+
$_.FullName, [ref]$null, [ref]$errors) | Out-Null
|
|
112
|
+
|
|
113
|
+
if ($errors -and $errors.Count -gt 0) {
|
|
114
|
+
$failed = $true
|
|
115
|
+
Write-Host "FAIL $($_.Name): $($errors.Count) parse error(s)"
|
|
116
|
+
$errors | Sort-Object { $_.Extent.StartLineNumber } | ForEach-Object {
|
|
117
|
+
Write-Host " L$($_.Extent.StartLineNumber): $($_.Message)"
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
Write-Host "OK $($_.Name)"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if ($failed) { exit 1 }
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
name: Publish dev build to PyPI
|
|
2
|
+
|
|
3
|
+
# Every merge to main publishes a PEP 440 dev release (e.g. 0.3.10.dev7) to
|
|
4
|
+
# PyPI, so the latest main is always installable from the real index with real
|
|
5
|
+
# dependency resolution. Dev releases are pre-releases: pip and uv skip them
|
|
6
|
+
# unless asked, so ordinary installs keep getting the latest stable.
|
|
7
|
+
#
|
|
8
|
+
# Tagged releases (including rc/beta/alpha) are handled by publish-to-pypi.yml.
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
branches: [main]
|
|
12
|
+
# Ad-hoc runs, e.g. re-publishing after a PyPI outage.
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
# Least privilege by default: jobs get no GITHUB_TOKEN scopes unless they
|
|
16
|
+
# opt in below.
|
|
17
|
+
permissions: {}
|
|
18
|
+
|
|
19
|
+
# Serialize publishes so versions land in merge order. Queued runs are not
|
|
20
|
+
# cancelled — each merge should still get its own dev build.
|
|
21
|
+
concurrency:
|
|
22
|
+
group: publish-dev-to-pypi
|
|
23
|
+
cancel-in-progress: false
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
name: Build dev distribution
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
outputs:
|
|
32
|
+
should-publish: ${{ steps.version.outputs.should-publish }}
|
|
33
|
+
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
with:
|
|
37
|
+
# hatch-vcs derives the version from git tags, so we need full history.
|
|
38
|
+
fetch-depth: 0
|
|
39
|
+
|
|
40
|
+
- name: Install uv
|
|
41
|
+
# uv provisions its own Python (honoring requires-python), so no
|
|
42
|
+
# separate actions/setup-python step is needed.
|
|
43
|
+
run: |
|
|
44
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
45
|
+
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
46
|
+
|
|
47
|
+
- name: Compute dev version
|
|
48
|
+
id: version
|
|
49
|
+
# Between releases hatch-vcs produces something like
|
|
50
|
+
# "0.3.10.dev16+gb710c2982". The "+g..." local version segment is valid
|
|
51
|
+
# PEP 440 but is rejected by PyPI on upload, so it has to go. We keep
|
|
52
|
+
# setuptools-scm's own next-version guess (0.3.10 — the patch bump
|
|
53
|
+
# after the latest tag) rather than re-deriving it here, and use the
|
|
54
|
+
# run number as the dev counter: it is strictly increasing, so each
|
|
55
|
+
# merge sorts after the last and re-runs never collide.
|
|
56
|
+
run: |
|
|
57
|
+
RAW=$(uvx --from setuptools-scm python -c \
|
|
58
|
+
"from setuptools_scm import get_version; print(get_version())")
|
|
59
|
+
echo "setuptools-scm reports: $RAW"
|
|
60
|
+
|
|
61
|
+
# On a commit that IS a release tag, setuptools-scm returns a clean
|
|
62
|
+
# version with no .dev component (e.g. "0.3.9" or "0.4.0rc1").
|
|
63
|
+
# Appending ".dev<run>" to that yields 0.3.9.dev42, which sorts BELOW
|
|
64
|
+
# the released 0.3.9 — newer code would look older. A tagged commit
|
|
65
|
+
# is a real release and is published by publish-to-pypi.yml, so there
|
|
66
|
+
# is no dev build to make here.
|
|
67
|
+
case "$RAW" in
|
|
68
|
+
*.dev*) ;;
|
|
69
|
+
*)
|
|
70
|
+
echo "::notice::$RAW is a tagged release; skipping dev build."
|
|
71
|
+
echo "should-publish=false" >> $GITHUB_OUTPUT
|
|
72
|
+
exit 0
|
|
73
|
+
;;
|
|
74
|
+
esac
|
|
75
|
+
|
|
76
|
+
BASE=${RAW%%+*}
|
|
77
|
+
BASE=${BASE%%.dev*}
|
|
78
|
+
VERSION="${BASE}.dev${GITHUB_RUN_NUMBER}"
|
|
79
|
+
echo "Derived version: $RAW -> $VERSION"
|
|
80
|
+
echo "SETUPTOOLS_SCM_PRETEND_VERSION=$VERSION" >> $GITHUB_ENV
|
|
81
|
+
echo "should-publish=true" >> $GITHUB_OUTPUT
|
|
82
|
+
|
|
83
|
+
- name: Build package
|
|
84
|
+
if: steps.version.outputs.should-publish == 'true'
|
|
85
|
+
# hatch-vcs reads SETUPTOOLS_SCM_PRETEND_VERSION in place of the tag.
|
|
86
|
+
run: |
|
|
87
|
+
uv build
|
|
88
|
+
echo "Built distributions:"
|
|
89
|
+
ls -l dist/
|
|
90
|
+
|
|
91
|
+
- name: Store the distribution packages
|
|
92
|
+
if: steps.version.outputs.should-publish == 'true'
|
|
93
|
+
uses: actions/upload-artifact@v4
|
|
94
|
+
with:
|
|
95
|
+
name: dev-package-distributions
|
|
96
|
+
path: dist/
|
|
97
|
+
|
|
98
|
+
publish-dev:
|
|
99
|
+
name: Publish dev build to PyPI
|
|
100
|
+
needs: build
|
|
101
|
+
if: needs.build.outputs.should-publish == 'true'
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
environment:
|
|
104
|
+
name: pypi
|
|
105
|
+
url: https://pypi.org/p/codeplain
|
|
106
|
+
permissions:
|
|
107
|
+
# Mint a short-lived OIDC token so PyPI Trusted Publishing can
|
|
108
|
+
# authenticate this run — no long-lived API token needed.
|
|
109
|
+
id-token: write
|
|
110
|
+
|
|
111
|
+
env:
|
|
112
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
113
|
+
|
|
114
|
+
steps:
|
|
115
|
+
- name: Download distribution packages
|
|
116
|
+
uses: actions/download-artifact@v4
|
|
117
|
+
with:
|
|
118
|
+
name: dev-package-distributions
|
|
119
|
+
path: dist/
|
|
120
|
+
|
|
121
|
+
- name: Publish to PyPI
|
|
122
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
123
|
+
with:
|
|
124
|
+
# PyPI uploads are immutable, so a re-run of an already-published
|
|
125
|
+
# version should be a no-op, not a red build.
|
|
126
|
+
skip-existing: true
|
|
127
|
+
|
|
128
|
+
# Success is deliberately quiet: this runs on every merge to main, which
|
|
129
|
+
# is already announced elsewhere. Only failures ping.
|
|
130
|
+
- name: Notify Slack (failure)
|
|
131
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
132
|
+
run: |
|
|
133
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
134
|
+
-H 'Content-type: application/json' \
|
|
135
|
+
--data "{\"text\":\"*Codeplain Client*: Publishing dev build to PyPI FAILED :x: (commit \`${{ github.sha }}\`). See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
@@ -14,6 +14,9 @@ jobs:
|
|
|
14
14
|
name: Upload to Cloudflare R2
|
|
15
15
|
runs-on: ubuntu-latest
|
|
16
16
|
|
|
17
|
+
env:
|
|
18
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
19
|
+
|
|
17
20
|
steps:
|
|
18
21
|
- uses: actions/checkout@v4
|
|
19
22
|
|
|
@@ -54,3 +57,17 @@ jobs:
|
|
|
54
57
|
--content-type "text/plain"
|
|
55
58
|
echo "✓ examples.ps1 uploaded to R2"
|
|
56
59
|
|
|
60
|
+
- name: Notify Slack (success)
|
|
61
|
+
if: ${{ success() && env.SLACK_WEBHOOK_URL != '' }}
|
|
62
|
+
run: |
|
|
63
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
64
|
+
-H 'Content-type: application/json' \
|
|
65
|
+
--data "{\"text\":\"*Codeplain Client*: Install scripts deployed to R2 :white_check_mark: (\`${GITHUB_SHA:0:7}\`, by *${{ github.actor }}*).\"}"
|
|
66
|
+
|
|
67
|
+
- name: Notify Slack (failure)
|
|
68
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
69
|
+
run: |
|
|
70
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
71
|
+
-H 'Content-type: application/json' \
|
|
72
|
+
--data "{\"text\":\"*Codeplain Client*: Install script deploy to R2 FAILED :x: (\`${GITHUB_SHA:0:7}\`). Users may be getting a stale installer. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
73
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
# Least privilege by default: jobs get no GITHUB_TOKEN scopes unless they
|
|
8
|
+
# opt in below.
|
|
9
|
+
permissions: {}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
# hatch-vcs derives the version from git tags, so we need full history.
|
|
25
|
+
fetch-depth: 0
|
|
26
|
+
|
|
27
|
+
- name: Notify Slack (start)
|
|
28
|
+
if: ${{ env.SLACK_WEBHOOK_URL != '' }}
|
|
29
|
+
run: |
|
|
30
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
31
|
+
-H 'Content-type: application/json' \
|
|
32
|
+
--data "{\"text\":\"*Codeplain Client*: Release \`${{ github.ref_name }}\` published by *${{ github.actor }}* — building and publishing to PyPI...\"}"
|
|
33
|
+
|
|
34
|
+
- name: Install uv
|
|
35
|
+
# uv provisions its own Python (honoring requires-python), so no
|
|
36
|
+
# separate actions/setup-python step is needed.
|
|
37
|
+
run: |
|
|
38
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
39
|
+
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
|
40
|
+
|
|
41
|
+
- name: Build package
|
|
42
|
+
# hatch-vcs reads the version straight from the release tag.
|
|
43
|
+
run: |
|
|
44
|
+
uv build
|
|
45
|
+
echo "Built distributions:"
|
|
46
|
+
ls -l dist/
|
|
47
|
+
|
|
48
|
+
- name: Store the distribution packages
|
|
49
|
+
uses: actions/upload-artifact@v4
|
|
50
|
+
with:
|
|
51
|
+
name: python-package-distributions
|
|
52
|
+
path: dist/
|
|
53
|
+
|
|
54
|
+
- name: Upload assets to GitHub Release
|
|
55
|
+
env:
|
|
56
|
+
GH_TOKEN: ${{ github.token }}
|
|
57
|
+
run: |
|
|
58
|
+
gh release upload ${{ github.ref_name }} dist/* --clobber
|
|
59
|
+
|
|
60
|
+
- name: Notify Slack (build failure)
|
|
61
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
62
|
+
run: |
|
|
63
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
64
|
+
-H 'Content-type: application/json' \
|
|
65
|
+
--data "{\"text\":\"*Codeplain Client*: Build of \`${{ github.ref_name }}\` FAILED :x:. Nothing was published to PyPI. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
66
|
+
|
|
67
|
+
publish-to-pypi:
|
|
68
|
+
name: Publish to PyPI
|
|
69
|
+
needs: build
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
environment:
|
|
72
|
+
name: pypi
|
|
73
|
+
url: https://pypi.org/p/codeplain
|
|
74
|
+
permissions:
|
|
75
|
+
# Mint a short-lived OIDC token so PyPI Trusted Publishing can
|
|
76
|
+
# authenticate this run — no long-lived API token needed.
|
|
77
|
+
id-token: write
|
|
78
|
+
|
|
79
|
+
env:
|
|
80
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
81
|
+
|
|
82
|
+
steps:
|
|
83
|
+
- name: Download distribution packages
|
|
84
|
+
uses: actions/download-artifact@v4
|
|
85
|
+
with:
|
|
86
|
+
name: python-package-distributions
|
|
87
|
+
path: dist/
|
|
88
|
+
|
|
89
|
+
- name: Publish to PyPI
|
|
90
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
91
|
+
|
|
92
|
+
- name: Notify Slack (success)
|
|
93
|
+
if: ${{ success() && env.SLACK_WEBHOOK_URL != '' }}
|
|
94
|
+
env:
|
|
95
|
+
# GitHub marks the release itself as a pre-release; the tag
|
|
96
|
+
# (v0.4.0rc1) carries the same intent for PEP 440.
|
|
97
|
+
IS_PRERELEASE: ${{ github.event.release.prerelease }}
|
|
98
|
+
TAG: ${{ github.ref_name }}
|
|
99
|
+
run: |
|
|
100
|
+
VERSION="${TAG#v}"
|
|
101
|
+
if [ "$IS_PRERELEASE" = "true" ]; then
|
|
102
|
+
# pip and uv skip pre-releases by default, so "--upgrade" would
|
|
103
|
+
# NOT pick this up. Tell people the command that actually works.
|
|
104
|
+
TEXT="*Codeplain Client*: pre-release \`$TAG\` published to PyPI :test_tube:. Normal installs are unaffected — try it with \`pip install --pre codeplain==$VERSION\`."
|
|
105
|
+
else
|
|
106
|
+
TEXT="*Codeplain Client*: \`$TAG\` published to PyPI :white_check_mark:. Install with \`pip install --upgrade codeplain\`."
|
|
107
|
+
fi
|
|
108
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
109
|
+
-H 'Content-type: application/json' \
|
|
110
|
+
--data "$(jq -n --arg t "$TEXT" '{text:$t}')"
|
|
111
|
+
|
|
112
|
+
- name: Notify Slack (failure)
|
|
113
|
+
if: ${{ failure() && env.SLACK_WEBHOOK_URL != '' }}
|
|
114
|
+
run: |
|
|
115
|
+
curl -s -X POST "$SLACK_WEBHOOK_URL" \
|
|
116
|
+
-H 'Content-type: application/json' \
|
|
117
|
+
--data "{\"text\":\"*Codeplain Client*: Publishing \`${{ github.ref_name }}\` to PyPI FAILED :x:. See <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|the run log>.\"}"
|
|
@@ -14,14 +14,14 @@ The codebase serves two audiences:
|
|
|
14
14
|
- **End users**: developers who write `***plain` specs and run `plain2code.py` to generate code
|
|
15
15
|
- **Internal devs**: maintaining the renderer itself (this codebase)
|
|
16
16
|
|
|
17
|
-
### Related Repository:
|
|
17
|
+
### Related Repository: codeplain-api
|
|
18
18
|
|
|
19
|
-
This repository has a sibling repository **`
|
|
19
|
+
This repository has a sibling repository **`codeplain-api`** which contains the backend API service that this client communicates with. The two repositories are typically cloned as siblings:
|
|
20
20
|
|
|
21
21
|
```
|
|
22
22
|
parent-directory/
|
|
23
|
-
├── codeplain/
|
|
24
|
-
└──
|
|
23
|
+
├── codeplain/ # This repository (client)
|
|
24
|
+
└── codeplain-api/ # Backend API service
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
**When to work across both repositories:**
|
|
@@ -212,8 +212,12 @@ Two logging modes:
|
|
|
212
212
|
### Code Generation Process
|
|
213
213
|
- Templates in `standard_template_library/` use Liquid2 syntax
|
|
214
214
|
- Template search order: (1) `.plain` file dir, (2) `--template-dir`, (3) built-in standard lib
|
|
215
|
-
-
|
|
216
|
-
-
|
|
215
|
+
- Each module renders into its own tree under the build folder (configurable via `--build-folder`, default `plain_modules/`):
|
|
216
|
+
- `<build-folder>/<module>/code/` — implementation code (its own git repo)
|
|
217
|
+
- `<build-folder>/<module>/tests/` — conformance tests (its own git repo; only created when a conformance tests script is configured)
|
|
218
|
+
- `<build-folder>/<module>/.codeplain/` — module metadata (`module_metadata.json`), not tracked in git
|
|
219
|
+
- `<build-folder>/<module>/.memory/` — conformance test memory, not tracked in git
|
|
220
|
+
- Each FRID render produces a git commit in the `code/` and `tests/` repos for rollback capability
|
|
217
221
|
|
|
218
222
|
### Configuration
|
|
219
223
|
- `config.yaml` can be placed in `.plain` file dir or CWD
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Contributing to Codeplain
|
|
2
|
+
|
|
3
|
+
Thanks for contributing to Codeplain.
|
|
4
|
+
|
|
5
|
+
## Before You Start
|
|
6
|
+
|
|
7
|
+
Check existing issues and pull requests before starting work.
|
|
8
|
+
|
|
9
|
+
Keep each contribution focused on one issue or a closely related set of changes.
|
|
10
|
+
|
|
11
|
+
## Contribution Workflow
|
|
12
|
+
|
|
13
|
+
1. Fork the Codeplain repository.
|
|
14
|
+
2. Make your changes on a branch in your fork.
|
|
15
|
+
3. Commit and push the changes to your fork.
|
|
16
|
+
4. Open a pull request against the Codeplain `main` branch.
|
|
17
|
+
|
|
18
|
+
## Configure Codeplain
|
|
19
|
+
|
|
20
|
+
Use your own Codeplain API key for local development and testing.
|
|
21
|
+
|
|
22
|
+
Never commit API keys, credentials, or other secrets.
|
|
23
|
+
|
|
24
|
+
## Test with a Plain Example
|
|
25
|
+
|
|
26
|
+
When relevant, test your change with an existing example from the `plainlang-examples` repository.
|
|
27
|
+
|
|
28
|
+
This provides a real `.plain` project for verifying the change in an actual Codeplain workflow.
|
|
29
|
+
|
|
30
|
+
## Run Tests
|
|
31
|
+
|
|
32
|
+
Run the tests relevant to your change before opening a pull request.
|
|
33
|
+
|
|
34
|
+
For changes that affect the CLI, rendering, or test execution, also test the change by running the relevant Codeplain command from the terminal.
|
|
35
|
+
|
|
36
|
+
Check that:
|
|
37
|
+
|
|
38
|
+
* the command returns the expected exit code,
|
|
39
|
+
* errors are clear and do not expose unintended tracebacks,
|
|
40
|
+
* existing Codeplain behavior still works.
|
|
41
|
+
|
|
42
|
+
For platform-specific changes, test the relevant `.sh` or `.ps1` workflow.
|
|
43
|
+
|
|
44
|
+
## Keep the Change Clean
|
|
45
|
+
|
|
46
|
+
Before submitting:
|
|
47
|
+
|
|
48
|
+
* remove temporary files and debugging output,
|
|
49
|
+
* avoid unrelated changes,
|
|
50
|
+
* add or update tests where needed,
|
|
51
|
+
* update documentation when behavior changes,
|
|
52
|
+
* verify that no secrets are included.
|
|
53
|
+
|
|
54
|
+
Review your changes with:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git status
|
|
58
|
+
git diff
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Pull Request
|
|
62
|
+
|
|
63
|
+
Include:
|
|
64
|
+
|
|
65
|
+
* what changed,
|
|
66
|
+
* why it changed,
|
|
67
|
+
* the related issue, when applicable,
|
|
68
|
+
* how the change was tested,
|
|
69
|
+
* the `plainlang-examples` example used, when relevant.
|
|
70
|
+
|
|
71
|
+
## Pre-Releases
|
|
72
|
+
|
|
73
|
+
Everything below happens on real PyPI — there is no separate test index.
|
|
74
|
+
Pre-releases are invisible to ordinary installs: pip and uv skip them during
|
|
75
|
+
resolution, so `pip install codeplain` and `pip install --upgrade codeplain`
|
|
76
|
+
always serve the latest *stable* release.
|
|
77
|
+
|
|
78
|
+
### Dev builds (automatic)
|
|
79
|
+
|
|
80
|
+
Every merge to `main` publishes a dev release such as `0.3.10.dev7`, so the tip
|
|
81
|
+
of main is always installable from the real index:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install --pre codeplain==0.3.10.dev7
|
|
85
|
+
uv tool install --prerelease allow codeplain
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Versions are `<next-patch>.dev<run-number>`, so they sort after the last
|
|
89
|
+
release and before the next one. See `.github/workflows/publish-dev-to-pypi.yml`.
|
|
90
|
+
If that workflow is ever dispatched against a commit that is itself a release
|
|
91
|
+
tag, it skips rather than publishing a dev build that would sort below the
|
|
92
|
+
release.
|
|
93
|
+
|
|
94
|
+
### Release candidates (manual)
|
|
95
|
+
|
|
96
|
+
To get a specific build in front of people before it becomes the default
|
|
97
|
+
install, cut a PEP 440 pre-release.
|
|
98
|
+
|
|
99
|
+
Tag and publish a GitHub release as usual, but with a pre-release version and
|
|
100
|
+
the release marked "pre-release":
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
v0.4.0a1 alpha
|
|
104
|
+
v0.4.0b1 beta
|
|
105
|
+
v0.4.0rc1 release candidate
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`publish-to-pypi.yml` handles these with no special casing: hatch-vcs reads the
|
|
109
|
+
version straight off the tag (`v0.4.0rc1` -> `0.4.0rc1`).
|
|
110
|
+
|
|
111
|
+
Opt in the same way:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install --pre codeplain==0.4.0rc1
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Which API a build talks to
|
|
118
|
+
|
|
119
|
+
Pre-release builds default to the **test** API, so an unreleased client is
|
|
120
|
+
exercised against the unreleased backend:
|
|
121
|
+
|
|
122
|
+
| build | default API |
|
|
123
|
+
| --- | --- |
|
|
124
|
+
| stable release (`0.3.9`) | `https://api.codeplain.ai` |
|
|
125
|
+
| dev build (`0.3.10.dev7`) | `https://api.test.codeplain.ai` |
|
|
126
|
+
| alpha/beta/rc (`0.4.0rc1`) | `https://api.test.codeplain.ai` |
|
|
127
|
+
|
|
128
|
+
`--api` always overrides this. Resolution lives in
|
|
129
|
+
`system_config._resolve_default_api_url`, keyed off the version baked into the
|
|
130
|
+
package at build time — so nothing needs configuring at install time.
|
|
131
|
+
|
|
132
|
+
A source checkout reports the nearest git tag as its version, so it is treated
|
|
133
|
+
as stable and keeps pointing at production; use `--api` to aim it elsewhere.
|
|
134
|
+
|
|
135
|
+
Because every build above goes to real PyPI, dependency resolution and the
|
|
136
|
+
install path are exactly what an end user gets — the main reason this is
|
|
137
|
+
preferred over publishing to TestPyPI.
|