diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index 73a3f0b1f..37c15eb2f 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -8,6 +8,8 @@ on: jobs: deploy-docs: runs-on: ubuntu-latest + # Only deploy docs for stable releases (not pre-releases) + if: github.event.release.prerelease == false steps: - uses: actions/checkout@v4 with: @@ -30,4 +32,6 @@ jobs: - name: Deploy docs run: | VERSION=${GITHUB_REF#refs/tags/v} - mike deploy --push --update-aliases $VERSION latest \ No newline at end of file + echo "Deploying docs for stable release: $VERSION" + mike deploy --push --update-aliases $VERSION latest + mike set-default --push latest \ No newline at end of file diff --git a/.github/workflows/python-app.yaml b/.github/workflows/python-app.yaml index abaef42e1..1896150f3 100644 --- a/.github/workflows/python-app.yaml +++ b/.github/workflows/python-app.yaml @@ -56,12 +56,49 @@ jobs: - name: Run tests run: pytest -v -p no:warnings + create-release: + name: Create Release with Changelog + runs-on: ubuntu-22.04 + needs: [test] + if: startsWith(github.ref, 'refs/tags/v') + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Sync changelog to docs + run: | + cp CHANGELOG.md docs/changelog.md + echo "✅ Synced changelog to docs" + + - name: Extract release notes + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "Extracting release notes for version: $VERSION" + python scripts/extract_release_notes.py $VERSION > current_release_notes.md + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + body_path: current_release_notes.md + draft: false + prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish-testpypi: name: Publish to TestPyPI runs-on: ubuntu-22.04 - needs: [test] # Only run after tests pass - if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation - + needs: [test, create-release] # Run after tests and release creation + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -86,7 +123,7 @@ jobs: env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} - + - name: Test install from TestPyPI run: | # Create a temporary environment to test installation @@ -104,8 +141,8 @@ jobs: publish-pypi: name: Publish to PyPI runs-on: ubuntu-22.04 - needs: [test] # Only run after TestPyPI publish succeeds - if: github.event_name == 'release' && github.event.action == 'created' # Only on release creation + needs: [publish-testpypi] # Only run after TestPyPI publish succeeds + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # Only on tag push steps: - name: Checkout repository diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..22acad1cd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,72 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [2.1.1] - 2025-05-08 + +### Fixed +- Fixed bug in the `_ElementResults.constraints` not returning the constraints but rather the variables + +### Changed +- Improved docstring and tests + +## [2.1.0] - 2025-04-11 + +### Added +- Python 3.13 support added +- Logger warning if relative_minimum is used without on_off_parameters in Flow +- Greatly improved internal testing infrastructure by leveraging linopy's testing framework + +### Fixed +- Fixed the lower bound of `flow_rate` when using optional investments without OnOffParameters +- Fixed bug that prevented divest effects from working +- Added lower bounds of 0 to two unbounded vars (numerical improvement) + +### Changed +- **BREAKING**: Restructured the modeling of the On/Off state of Flows or Components + - Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours` + - Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours` + - Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1` + - Similar pattern for all consecutive on/off constraints + +## [2.0.1] - 2025-04-10 + +### Added +- Logger warning if relative_minimum is used without on_off_parameters in Flow + +### Fixed +- Replace "|" with "__" in filenames when saving figures (Windows compatibility) +- Fixed bug that prevented the load factor from working without InvestmentParameters + +## [2.0.0] - 2025-03-29 + +### Changed +- **BREAKING**: Complete migration from Pyomo to Linopy optimization framework +- **BREAKING**: Redesigned data handling to rely on xarray.Dataset throughout the package +- **BREAKING**: Framework renamed from flixOpt to flixopt (`import flixopt as fx`) +- **BREAKING**: Results handling completely redesigned with new `CalculationResults` class + +### Added +- Full model serialization support - save and restore unsolved Models +- Enhanced model documentation with YAML export containing human-readable mathematical formulations +- Extend flixopt models with native linopy language support +- Full Model Export/Import capabilities via linopy.Model +- Unified solution exploration through `Calculation.results` attribute +- Compression support for result files +- `to_netcdf/from_netcdf` methods for FlowSystem and core components +- xarray integration for TimeSeries with improved datatypes support +- Google Style Docstrings throughout the codebase + +### Fixed +- Improved infeasible model detection and reporting +- Enhanced time series management and serialization +- Reduced file size through improved compression + +### Removed +- **BREAKING**: Pyomo dependency (replaced by linopy) +- Period concepts in time management (simplified to timesteps) \ No newline at end of file diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 7afca119d..fffb84610 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -4,4 +4,4 @@ - [Examples](examples/) - [FAQ](faq/) - [API-Reference](api-reference/) -- [Release Notes](release-notes/) \ No newline at end of file +- [Release Notes](changelog.md) \ No newline at end of file diff --git a/docs/release-notes/_template.txt b/docs/release-notes/_template.txt deleted file mode 100644 index fe85a0554..000000000 --- a/docs/release-notes/_template.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Release v{version} - -**Release Date:** YYYY-MM-DD - -## What's New - -* Feature 1 - Description -* Feature 2 - Description - -## Improvements - -* Improvement 1 - Description -* Improvement 2 - Description - -## Bug Fixes - -* Fixed issue with X -* Resolved problem with Y - -## Breaking Changes - -* Change 1 - Migration instructions -* Change 2 - Migration instructions - -## Deprecations - -* Feature X will be removed in v{next_version} - -## Dependencies - -* Added dependency X v1.2.3 -* Updated dependency Y to v2.0.0 \ No newline at end of file diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md deleted file mode 100644 index fecb3d61b..000000000 --- a/docs/release-notes/index.md +++ /dev/null @@ -1,7 +0,0 @@ -# Release Notes - -This page provides links to release notes for all versions of flixopt. - -## Latest Release - -* [v2.0.0](v2.0.0.md) - 29.03.2025 - Migration from pyomo to linopy. Alround improvements in performance and usability diff --git a/docs/release-notes/v2.0.0.md b/docs/release-notes/v2.0.0.md deleted file mode 100644 index 008d1360d..000000000 --- a/docs/release-notes/v2.0.0.md +++ /dev/null @@ -1,93 +0,0 @@ -# Release v2.0.0 - -**Release Date:** March 29, 2025 - -## 🚀 Major Framework Changes - -- **Migration from Pyomo to Linopy**: Completely rebuilt the optimization foundation to use Linopy instead of Pyomo - - Significant performance improvements, especially for large models - - Internal useage of linopys mathematical modeling language -- **xarray-Based Data Architecture**: Redesigned data handling to rely on xarray.Dataset throughout the package for: - - Improved solution representation and analysis - - Enhanced time series management - - Consistent serialization across all elements - - Reduced file size and improved performance -- **Saving and restoring unsolved Models**: The FlowSystem is now fully serializable and can be saved to a file. - - Share your work with others by saving the FlowSystem to a file - - Load a FlowSystem from a file to extend or modify your work - -## 🔧 Key Improvements - -### Model Handling - -- **Extend every flixopt model with the linopy language**: Add any additional constraint or variable to your flixopt model by using the linopy language. -- **Full Model Export/Import**: As a result of the migration to Linopy, the linopy.Model can be exported before or after the solve. -- **Improved Infeasible Model Handling**: Added better detection and reporting for infeasible optimization models -- **Improved Model Documentation**: Every model can be documented in a .yaml file, containing human readable mathematical formulations of all variables and constraints. THis is used to document every Calculation. - -### Calculation Results and documentation: -The `CalculationResults` class has been completely redesigned to provide a more streamlined and intuitive interface. -Accessing the results of a Calculation is now as simple as: -```python -fx.FullCalculation('Sim1', flow_system) -calculation.solve(fx.solvers.HighsSolver()) -calculation.results # This object can be entirely saved and reloaded to file without any information loss -``` -This access doesn't change if you save and load the results to a file or use them in your script directly! - -- **Improved Documentation**: The FlowSystem as well as a model Documentation is created for every model run. -- **Results without saving to file**: The results of a Calculation can now be properly accessed without saving the results to a file first. -- **Unified Solution exploration**: Every `Calculation` has a `Calculation.results` attribute, which accesses the solution. This can be saved and reloaded without any information loss. -- **Improved Calculation Results**: The results of a Calculation are now more intuitive and easier to access. The `CalculationResults` class has been completely redesigned to provide a more streamlined and intuitive interface. - -### Data Management & I/O - -- **Unified Serialization**: Standardized serialization and deserialization across all elements -- **Compression Support**: Added data compression when saving results to reduce file size -- **to_netcdf/from_netcdf Methods**: Added for FlowSystem and other core components - -### Details -#### TimeSeries Enhancements - -- **xarray Integration**: Redesigned TimeSeries to depend on xr.DataArray -- **datatypes**: Added support for more datatypes, with methods for conversion to TimeSeries -- **Improved TimeSeriesCollection**: Enhanced indexing, representation, and dataset conversion -- **Simplified Time Management**: Removed period concepts and focused on timesteps for more intuitive time handling - -## 📚 Documentation - -- Improved documentation of the FlixOpt API and mathematical formulations -- **Google Style Docstrings**: Updated all docstrings to Google style format - -## 🔄 Dependencies - -- **Linopy**: Added as the core dependency replacing Pyomo -- **xarray**: Now a critical dependency for data handling and file I/O -- **netcdf4**: Dependency for fast and efficient file I/O - -### Dropped Dependencies -- **pyomo**: Replaced by linopy as the modeling language - -## 📋 Migration Notes - -This version represents a significant architecture change. If you're upgrading: - -- Code that directly accessed Pyomo models will need to be updated to work with Linopy -- Data handling now uses xarray.Dataset throughout, which may require changes in how you interact with results -- The way labels are constructed has changed throughout the system -- The results of calculations are now handled differently, and may require changes in how you access results -- The framework was renamed from flixOpt to flixopt. Use `import flixopt as fx`. - -For complete details, please refer to the full commit history. - -## Installation - -```bash -pip install flixopt==2.0.0 -``` - -## Upgrading - -```bash -pip install --upgrade flixopt -``` \ No newline at end of file diff --git a/docs/release-notes/v2.0.1.md b/docs/release-notes/v2.0.1.md deleted file mode 100644 index 9b6884e48..000000000 --- a/docs/release-notes/v2.0.1.md +++ /dev/null @@ -1,12 +0,0 @@ -# Release v2.0.1 - -**Release Date:** 2025-04-10 - -## Improvements - -* Add logger warning if relative_minimum is used without on_off_parameters in Flow, as this prevents the flow_rate from switching "OFF" - -## Bug Fixes - -* Replace "|" with "__" in filenames when saving figures, as "|" can lead to issues on windows -* Fixed a Bug that prevented the load factor from working without InvestmentParameters diff --git a/docs/release-notes/v2.1.0.md b/docs/release-notes/v2.1.0.md deleted file mode 100644 index 09972c5f7..000000000 --- a/docs/release-notes/v2.1.0.md +++ /dev/null @@ -1,31 +0,0 @@ -# Release v2.1.0 - -**Release Date:** 2025-04-11 - -## Improvements - -* Add logger warning if relative_minimum is used without on_off_parameters in Flow, as this prevents the flow_rate from switching "OFF" -* Python 3.13 support added -* Greatly improved internal testing infrastructure by leveraging linopy's testing framework - -## Bug Fixes - -* Bugfixing the lower bound of `flow_rate` when using optional investments without OnOffParameters. -* Fixes a Bug that prevented divest effects from working. -* added lower bounds of 0 to two unbounded vars (only numerical better) - -## Breaking Changes - -* We restructured the modeling of the On/Off state of FLows or Components. This leads to slightly renaming of variables and constraints. - -### Variable renaming -* "...|consecutive_on_hours" is now "...|ConsecutiveOn|hours" -* "...|consecutive_off_hours" is now "...|ConsecutiveOff|hours" - -### Constraint renaming -* "...|consecutive_on_hours_con1" is now "...|ConsecutiveOn|con1" -* "...|consecutive_on_hours_con2a" is now "...|ConsecutiveOn|con2a" -* "...|consecutive_on_hours_con2b" is now "...|ConsecutiveOn|con2b" -* "...|consecutive_on_hours_initial" is now "...|ConsecutiveOn|initial" -* "...|consecutive_on_hours_minimum_duration" is now "...|ConsecutiveOn|minimum" -The same goes for "...|consecutive_off..." --> "...|ConsecutiveOff|..." \ No newline at end of file diff --git a/docs/release-notes/v2.1.1.md b/docs/release-notes/v2.1.1.md deleted file mode 100644 index 44e635f87..000000000 --- a/docs/release-notes/v2.1.1.md +++ /dev/null @@ -1,11 +0,0 @@ -# Release v2.1.1 - -**Release Date:** 2025-05-08 - -## Improvements - -* Improving docstring and tests - -## Bug Fixes - -* Fixing bug in the `_ElementResults.constraints` not returning the constraints but rather the variables diff --git a/mkdocs.yml b/mkdocs.yml index ebf4ac0d9..fb009b1fd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -79,12 +79,13 @@ markdown_extensions: - pymdownx.snippets: base_path: .. - plugins: - search # Enables the search functionality in the documentation - table-reader # Allows including tables from external files - include-markdown - - mike + - mike: + version_selector: true + default_version: latest - gen-files: scripts: - scripts/gen_ref_pages.py diff --git a/scripts/extract_release_notes.py b/scripts/extract_release_notes.py new file mode 100644 index 000000000..61ee16425 --- /dev/null +++ b/scripts/extract_release_notes.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +""" +Extract release notes from CHANGELOG.md for a specific version. +Usage: python extract_release_notes.py +""" + +import re +import sys +from pathlib import Path + + +def extract_release_notes(version: str) -> str: + """Extract release notes for a specific version from CHANGELOG.md""" + changelog_path = Path("CHANGELOG.md") + + if not changelog_path.exists(): + print("❌ Error: CHANGELOG.md not found", file=sys.stderr) + sys.exit(1) + + content = changelog_path.read_text(encoding='utf-8') + + # Pattern to match version section: ## [2.1.2] - 2025-06-14 + pattern = rf'## \[{re.escape(version)}\] - [^\n]+\n(.*?)(?=\n## \[|\n\[Unreleased\]|\Z)' + match = re.search(pattern, content, re.DOTALL) + + if not match: + print(f"❌ Error: No release notes found for version '{version}'", file=sys.stderr) + sys.exit(1) + + return match.group(1).strip() + + +def main(): + if len(sys.argv) != 2: + print("Usage: python extract_release_notes.py ") + print("Example: python extract_release_notes.py 2.1.2") + sys.exit(1) + + version = sys.argv[1] + release_notes = extract_release_notes(version) + print(release_notes) + + +if __name__ == "__main__": + main() diff --git a/site/release-notes/_template.txt b/site/release-notes/_template.txt deleted file mode 100644 index fe85a0554..000000000 --- a/site/release-notes/_template.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Release v{version} - -**Release Date:** YYYY-MM-DD - -## What's New - -* Feature 1 - Description -* Feature 2 - Description - -## Improvements - -* Improvement 1 - Description -* Improvement 2 - Description - -## Bug Fixes - -* Fixed issue with X -* Resolved problem with Y - -## Breaking Changes - -* Change 1 - Migration instructions -* Change 2 - Migration instructions - -## Deprecations - -* Feature X will be removed in v{next_version} - -## Dependencies - -* Added dependency X v1.2.3 -* Updated dependency Y to v2.0.0 \ No newline at end of file