diff --git a/.github/actions/build-release/action.yml b/.github/actions/build-release/action.yml new file mode 100644 index 000000000..d65b3b1a9 --- /dev/null +++ b/.github/actions/build-release/action.yml @@ -0,0 +1,76 @@ +name: "Build a release" +description: "Create the dist files for a specific version" + +inputs: + tag: + description: 'The tag we want to create the release for' + required: true + # @FIX: this should not be required? + commit_sha: + description: 'The commit of the tag' + required: true + encryption_key: + description: 'The key used to encypt the detailed processes' + required: true + private_ssh_key: + description: 'The private ssh key used to clone the detailed impacts' + required: true + ecobalyse_data_dir: + description: 'The path to the ecobalyse dir containing the detailed impacts' + required: false + default: "./ecobalyse-private" +outputs: + dist-archive: + description: "Dist archive file path" + value: ${{ steps.create-dist-archive.outputs.dist-archive }} + + +runs: + using: "composite" + steps: + + - uses: actions/setup-node@v4 + with: + node-version: "20.x" + cache: 'npm' + + - name: Install Node dependencies + shell: bash + run: npm ci --prefer-offline --no-audit + + - name: Clone the detailed impacts + shell: bash + run: | + eval `ssh-agent -s` + ssh-add - <<< '${{ inputs.private_ssh_key }}' + git clone git@github.com:MTES-MCT/ecobalyse-private.git + + - name: Build app + shell: bash + env: + # Specify the created SHA to correctly update version.json + # @FIX: this should not be requiered when creating a tagged version + SOURCE_VERSION: ${{ inputs.commit_sha }} + TAG: ${{ inputs.tag }} + ECOBALYSE_DATA_DIR: ${{ inputs.ecobalyse_data_dir }} + run: | + npm run build:standalone-app + + - name: Encrypt the impacts files + shell: bash + env: + ENCRYPTION_KEY: ${{ inputs.encryption_key }} + ECOBALYSE_DATA_DIR: ${{ inputs.ecobalyse_data_dir }} + run : | + # We include the encrypted detailed processes with the dist + # so that people with the encryption key could later on use the app with the exact + # files it was using on production + npm run encrypt $ECOBALYSE_DATA_DIR/data/textile/processes_impacts.json dist/processes_impacts_textile.json.enc + npm run encrypt $ECOBALYSE_DATA_DIR/data/food/processes_impacts.json dist/processes_impacts_food.json.enc + + - name: Generate dist archive + shell: bash + id: create-dist-archive + run: | + tar czvf ${{ inputs.tag }}-dist.tar.gz dist + echo "dist-archive=${{ inputs.tag }}-dist.tar.gz" >> $GITHUB_OUTPUT diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 000000000..a58707f55 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,98 @@ +name: Generate changelog + +on: + push: + branches: [ master, staging ] + pull_request: + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + changelog: + name: Generate changelog + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate the full changelog + uses: orhun/git-cliff-action@v4 + id: git-cliff + with: + config: cliff.toml + args: --verbose --exclude-path "data/" --bump + env: + OUTPUT: CHANGELOG-cliff.md + + - name: Generate latest changes + uses: orhun/git-cliff-action@v4 + id: git-cliff-latest + with: + config: cliff.toml + args: --verbose --exclude-path "data/" --bump --unreleased + env: + GITHUB_REPO: ${{ github.repository }} + + - name: Extract branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Create Pull Request + id: cpr + uses: peter-evans/create-pull-request@v7 + with: + base: master + commit-message: Update changelog + signoff: false + branch: chore/update-changelog-${{ steps.git-cliff.outputs.version }} + delete-branch: true + title: 'chore(release): Release ${{ steps.git-cliff.outputs.version }}' + body: ${{ steps.git-cliff-latest.outputs.content }} + labels: | + pending-release + automated pr + + + # - name: Commit the changelog + # run: | + # git checkout ${{ steps.extract_branch.outputs.branch }} + # git config user.name 'github-actions[bot]' + # git config user.email 'github-actions[bot]@users.noreply.github.com' + # set +e + # git add CHANGELOG-cliff.md + # git commit -m "Update changelog" + # git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git ${{ steps.extract_branch.outputs.branch }} + # + # - name: Tag the next version + # run: | + # git checkout ${{ steps.extract_branch.outputs.branch }} + # git config user.name 'github-actions[bot]' + # git config user.email 'github-actions[bot]@users.noreply.github.com' + # set +e + # git tag -f ${{ steps.git-cliff.outputs.version }}-cliff-test + # git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git ${{ steps.git-cliff.outputs.version }}-cliff-test + # + # - name: Create dist archive + # uses: ./.github/actions/build-release + # id: create-dist-archive + # with: + # tag: ${{ steps.git-cliff.outputs.version }}-cliff-test + # commit_sha: ${{ github.event.pull_request.head.sha }} + # encryption_key: ${{ secrets.ENCRYPTION_KEY }} + # private_ssh_key: ${{ secrets.PRIVATE_SSH_KEY }} + # + # + # - name: Upload the release + # uses: svenstaro/upload-release-action@v2 + # with: + # file: ${{ steps.create-dist-archive.outputs.dist-archive}} + # repo_token: ${{ secrets.GITHUB_TOKEN }} + # tag: ${{ steps.git-cliff.outputs.version }}-cliff-test + # body: ${{ steps.git-cliff-latest.outputs.content }} + # draft: true diff --git a/CHANGELOG-cliff.md b/CHANGELOG-cliff.md new file mode 100644 index 000000000..0e0c73626 --- /dev/null +++ b/CHANGELOG-cliff.md @@ -0,0 +1,19 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [2.4.0] - 2024-09-26 + +### ๐Ÿš€ Features + +- Add `git-cliff` + +### ๐Ÿ› Bug Fixes + +- Don't download draft releases + +### โš™๏ธ Miscellaneous Tasks + +- Better logging + + diff --git a/bin/download_github_releases.py b/bin/download_github_releases.py index 333a8633a..3a9aa2b6e 100755 --- a/bin/download_github_releases.py +++ b/bin/download_github_releases.py @@ -81,6 +81,9 @@ def download_file(url, destination_directory=None): for asset in release.assets: if "-dist.tar.gz" in asset.browser_download_url: + logger.info( + f"Downloading {asset.browser_download_url} to {args.destination_directory}." + ) file_path = download_file( asset.browser_download_url, args.destination_directory ) diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 000000000..c5e5f1253 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,83 @@ +# git-cliff ~ default configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# template for the changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing s +trim = true +# postprocessors +postprocessors = [ + { pattern = '', replace = "https://github.com/MTES-MCT/ecobalyse" }, # replace repository URL +] +# render body even when there are no releases to process +# render_always = true +# output file path +# output = "test.md" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # Replace issue numbers + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit with https://github.com/crate-ci/typos + # If the spelling is incorrect, it will be automatically fixed. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "๐Ÿš€ Features" }, + { message = "^fix", group = "๐Ÿ› Bug Fixes" }, + { message = "^doc", group = "๐Ÿ“š Documentation" }, + { message = "^perf", group = "โšก Performance" }, + { message = "^refactor", group = "๐Ÿšœ Refactor" }, + { message = "^style", group = "๐ŸŽจ Styling" }, + { message = "^test", group = "๐Ÿงช Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, + { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, + { message = "^revert", group = "โ—€๏ธ Revert" }, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" diff --git a/package-lock.json b/package-lock.json index d0c76d854..9db532c7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "elm-json": "^0.2.13", "elm-review": "^2.12.0", "elm-test": "0.19.1-revision12", + "git-cliff": "^2.6.0", "highcharts": "^11.4.8", "jest": "^29.7.0", "nodemon": "^3.1.4", @@ -7167,6 +7168,241 @@ "assert-plus": "^1.0.0" } }, + "node_modules/git-cliff": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff/-/git-cliff-2.6.0.tgz", + "integrity": "sha512-ipMTSjMLjJN0z5AAWUvZJLBYISwu5NvmdrrXmsqwrJ1QXhOgsWOXobft86YH6JJVkKuyh/M4gdhNnAS0H4ldkw==", + "dev": true, + "dependencies": { + "execa": "^8.0.1" + }, + "bin": { + "git-cliff": "lib/cli/cli.js" + }, + "engines": { + "node": ">=18.19 || >=20.6 || >=21" + }, + "optionalDependencies": { + "git-cliff-darwin-arm64": "2.6.0", + "git-cliff-darwin-x64": "2.6.0", + "git-cliff-linux-arm64": "2.6.0", + "git-cliff-linux-x64": "2.6.0", + "git-cliff-windows-arm64": "2.6.0", + "git-cliff-windows-x64": "2.6.0" + } + }, + "node_modules/git-cliff-darwin-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-darwin-arm64/-/git-cliff-darwin-arm64-2.6.0.tgz", + "integrity": "sha512-WdBQmeLKDjJWl/Y6djgwqEUh8eYTJ5ljLea2M8qDhlEBMoC9Ew3VcRmdfTy2fSIxm7WBZm9T6ukkQj4vCv099Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/git-cliff-darwin-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-darwin-x64/-/git-cliff-darwin-x64-2.6.0.tgz", + "integrity": "sha512-Zvio86pLAbFGI5khYtVloecKxOac9JV9gL8MR8Eb+1hsliH+LY6MGCzy7zsrDCWEJ9+nH5qfMB24UwABsZhbMg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/git-cliff-linux-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-linux-arm64/-/git-cliff-linux-arm64-2.6.0.tgz", + "integrity": "sha512-FdeulZysE/JFhHmCKnNqXUnOexC4Zg+AloD7DBaiTP5Af2dpVLbV0upjFj2GfQE/x0eGhZH5BqZM5uY6ANuMFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/git-cliff-linux-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-linux-x64/-/git-cliff-linux-x64-2.6.0.tgz", + "integrity": "sha512-lQDjcT1ieJZaC6ULvWcG/0s3+RgItnEsNSD37Xwh/p7HWaz7FZaWrkVySgWSsDahE0GdYnR8v5hs1C1plT2d6w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/git-cliff-windows-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-windows-arm64/-/git-cliff-windows-arm64-2.6.0.tgz", + "integrity": "sha512-xREKhwIKJMZvUzU0nsu0pLt1LMMdWn3367OZoJTy1RyEzqAFpOZXdejuD0GSFCN/t9QgyDJWURQKFekyfKwYSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/git-cliff-windows-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/git-cliff-windows-x64/-/git-cliff-windows-x64-2.6.0.tgz", + "integrity": "sha512-wFnK2cizOrxpPZT4IHmSnUK0YQUuLuI4XZAJHepV4hU4GJWi6q1bIZGoQapRtfZ82bSEF+4EIstoDDoWVwmLGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/git-cliff/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/git-cliff/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/git-cliff/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-cliff/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/git-cliff/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", diff --git a/package.json b/package.json index 3b1f0727b..3dfe0d400 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "build": "npm run server:build && rimraf dist && npm run build:init && parcel build index.html --public-url ./", "build:init": "./bin/update-version.sh && mkdir -p dist && cp -r public/* dist/ && npm run db:build", "build:standalone-app": "npm run build && npm run server:build && cp server-app.js dist/ && cp openapi.yaml dist/", + "changelog:generate": "git-cliff -o CHANGELOG-cliff.md --exclude-path 'data/'", + "changelog:generate:bump": "npm run changelog:generate -- --bump", "decrypt": "./bin/decrypt", "encrypt": "./bin/encrypt", "db:build": "./bin/build-db && npm run db:check", @@ -65,25 +67,26 @@ }, "devDependencies": { "@apidevtools/swagger-cli": "^4.0.4", + "@parcel/transformer-elm": "^2.12.0", + "@parcel/transformer-image": "^2.12.0", + "@parcel/transformer-sass": "^2.12.0", + "bootstrap": "^5.3.3", "concurrently": "^8.2.2", + "elm": "^0.19.1-6", "elm-format": "^0.8.7", "elm-json": "^0.2.13", "elm-review": "^2.12.0", "elm-test": "0.19.1-revision12", + "git-cliff": "^2.6.0", + "highcharts": "^11.4.8", "jest": "^29.7.0", "nodemon": "^3.1.4", "npm-check-updates": "^17.1.0", + "parcel": "^2.12.0", "prettier": "^3.3.3", "process": "^0.11.10", "rimraf": "^6.0.1", - "supertest": "^7.0.0", - "parcel": "^2.12.0", - "@parcel/transformer-elm": "^2.12.0", - "@parcel/transformer-image": "^2.12.0", - "@parcel/transformer-sass": "^2.12.0", - "highcharts": "^11.4.8", - "bootstrap": "^5.3.3", - "elm": "^0.19.1-6" + "supertest": "^7.0.0" }, "cacheDirectories": [ "node_modules",