diff --git a/.github/.github_changelog_generator b/.github/.github_changelog_generator new file mode 100644 index 0000000000..482e8e1a55 --- /dev/null +++ b/.github/.github_changelog_generator @@ -0,0 +1,15 @@ +issues=true +issues-wo-labels=false +pr-wo-labels=false +author=false +breaking-label=Changed +breaking-labels=Breaking change +enhancement-label=Added +enhancement-labels=Added +bugs-label=Patch +bug-labels=Patch +deprecated-labels=Deprecated +removed-labels=Removed +exclude-labels=Documentation,No changelog +include-labels=Rust +verbose=true \ No newline at end of file diff --git a/.github/actions/publish/publish-wasm/action.yml b/.github/actions/publish/publish-wasm/action.yml new file mode 100644 index 0000000000..8208c18228 --- /dev/null +++ b/.github/actions/publish/publish-wasm/action.yml @@ -0,0 +1,43 @@ +name: 'publish-wasm' +description: 'Publishes Wasm bindings to npm' +inputs: + tag: + description: 'Which npm tag to publish under e.g. `dev`, will default to `latest`' + required: false + npm-token: + description: 'used for authenticating towards npm' + required: true +runs: + using: "composite" + steps: + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + target: wasm32-unknown-unknown + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + + - name: Install JS dependencies + shell: sh + run: npm install + working-directory: bindings/wasm + + - name: Build WASM bindings + shell: sh + run: npm run build + working-directory: bindings/wasm + + - name: Publish WASM bindings to NPM + shell: sh + env: + NODE_AUTH_TOKEN: ${{ inputs.npm-token }} + # will publish 'latest' tag if no tag is passed + run: npm publish $(if [ ${{ inputs.tag }} != '' ]; then echo --tag ${{ inputs.tag }}; fi) --access public + working-directory: bindings/wasm \ No newline at end of file diff --git a/.github/actions/release/bump-versions/action.yml b/.github/actions/release/bump-versions/action.yml new file mode 100644 index 0000000000..9a08c24de5 --- /dev/null +++ b/.github/actions/release/bump-versions/action.yml @@ -0,0 +1,69 @@ +name: 'bump-versions' +description: 'Bump project versions for the release target' +inputs: + release-target: + description: "target of the release (rust|wasm)" + required: true + version: + description: "version to set (e.g. `1.2.3` or `1.2.3-dev.1`)" + required: true + + +runs: + using: "composite" + steps: + - name: Install Rust stable toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + + - name: Install cargo-workspaces + uses: actions-rs/cargo@v1 + with: + command: install + args: --version ^0.2 cargo-workspaces + + - name: Install cargo-edit # to use cargo add + uses: actions-rs/cargo@v1 + if: ${{inputs.release-target == 'rust'}} + with: + command: install + args: -f --no-default-features --features "add" --version ^0.8 cargo-edit + + - name: Replace identity version in Wasm bindings + shell: bash + if: ${{inputs.release-target == 'rust'}} + working-directory: bindings/wasm + run: | + cargo add identity@=${{ inputs.version }} --path=../../identity + + - name: Bump Rust crate version + shell: bash + # cargo-release creates a signed commit automatically + if: ${{inputs.release-target == 'rust'}} + run: | + cargo workspaces version --no-git-commit --exact custom ${{ inputs.version }} -y + + - name: Bump Wasm bindings crate version + shell: bash + # cargo-release creates a signed commit automatically + if: ${{inputs.release-target == 'wasm'}} + working-directory: bindings/wasm + run: | + cargo workspaces version --no-git-commit --exact custom ${{ inputs.version }} -y + + - name: Set up Node.js + uses: actions/setup-node@v2 + if: ${{inputs.release-target == 'wasm'}} + with: + node-version: '16.x' + registry-url: 'https://registry.npmjs.org' + + - name: Bump Wasm npm package version + shell: bash + if: ${{inputs.release-target == 'wasm'}} + working-directory: bindings/wasm + run: | + npm version ${{ inputs.version }} \ No newline at end of file diff --git a/.github/actions/release/changelog-generator/action.yml b/.github/actions/release/changelog-generator/action.yml new file mode 100644 index 0000000000..53c5373b01 --- /dev/null +++ b/.github/actions/release/changelog-generator/action.yml @@ -0,0 +1,50 @@ +name: 'changelog-generator' +description: 'Runs github changelog generator' +inputs: + changelog-path: + description: "path to the changelog file" + required: false + default: ./CHANGELOG.md + changelog-config-path: + description: "path to the changelog config" + required: true + future-release: + description: "release name (e.g. `v1.2.3-dev.1`)" + required: true + optional-arg: + description: "optional argument for the generator command" + required: false + github-token: + description: "token used to call github API" + required: true + +runs: + using: "composite" + steps: + - name: Prepare Repository For Changelog Generator + shell: bash + run: | + GITHUB_REPOSITORY_USER=$( echo $GITHUB_REPOSITORY | awk -F'/' '{print $1}') + GITHUB_REPOSITORY_PROJECT=$( echo $GITHUB_REPOSITORY | awk -F'/' '{print $2}') + + echo GITHUB_REPOSITORY_USER=$GITHUB_REPOSITORY_USER + echo GITHUB_REPOSITORY_PROJECT=$GITHUB_REPOSITORY_PROJECT + + echo GITHUB_REPOSITORY_USER=$GITHUB_REPOSITORY_USER >> $GITHUB_ENV + echo GITHUB_REPOSITORY_PROJECT=$GITHUB_REPOSITORY_PROJECT >> $GITHUB_ENV + + - name: Run github-changelog-generator + uses: docker://githubchangeloggenerator/github-changelog-generator:1.16.2 + with: + args: > + --output ${{ inputs.changelog-path }} + --config-file ${{ inputs.changelog-config-path }} + --user ${{ env.GITHUB_REPOSITORY_USER }} + --project ${{ env.GITHUB_REPOSITORY_PROJECT }} + --token ${{ inputs.github-token }} + --future-release ${{ inputs.future-release }} + ${{ inputs.optional-arg }} + + - name: Log ${{ inputs.changelog-path }} + shell: bash + run: cat ${{ inputs.changelog-path }} \ No newline at end of file diff --git a/.github/workflows/enforce-pr-labels.yml b/.github/workflows/enforce-pr-labels.yml new file mode 100644 index 0000000000..6bc2f71b7a --- /dev/null +++ b/.github/workflows/enforce-pr-labels.yml @@ -0,0 +1,15 @@ +name: Enforce PR labels + +on: + pull_request: + types: [labeled, unlabeled, opened, reopened, edited, synchronize] +jobs: + enforce-label: + runs-on: ubuntu-latest + steps: + - uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 + with: + REQUIRED_LABELS_ANY: "Rust,Wasm,Documentation,No changelog" + - uses: yogevbd/enforce-label-action@a3c219da6b8fa73f6ba62b68ff09c469b3a1c024 + with: + REQUIRED_LABELS_ANY: "Breaking change,Added,Patch,Deprecated,Removed,Documentation,No changelog" \ No newline at end of file diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml deleted file mode 100644 index ff7275d50c..0000000000 --- a/.github/workflows/publish-dev.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Publish Dev - -on: - workflow_dispatch: - -jobs: - wasm: - runs-on: ubuntu-latest - strategy: - fail-fast: false - - steps: - - uses: actions/checkout@v2 - with: - ref: dev - - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - - name: Install WASM toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: wasm32-unknown-unknown - - - name: Set up Node.js - uses: actions/setup-node@v1 - with: - node-version: 16.x - registry-url: 'https://registry.npmjs.org' - - - name: Install JS dependencies - run: npm install - working-directory: bindings/wasm - - - name: Build WASM bindings - run: npm run build - working-directory: bindings/wasm - - - name: Publish WASM bindings to NPM - run: npm publish --tag dev --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - working-directory: bindings/wasm diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index d4c5692560..0000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Publish - -on: - workflow_dispatch: - -jobs: - wasm: - runs-on: ubuntu-latest - strategy: - fail-fast: false - - steps: - - uses: actions/checkout@v2 - - - name: Install stable toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true - - - name: Install WASM toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: wasm32-unknown-unknown - - - name: Set up Node.js - uses: actions/setup-node@v1 - with: - node-version: 16.x - registry-url: 'https://registry.npmjs.org' - - - name: Install JS dependencies - run: npm install - working-directory: bindings/wasm - - - name: Build WASM bindings - run: npm run build - working-directory: bindings/wasm - - - name: Publish WASM bindings to NPM - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - working-directory: bindings/wasm diff --git a/.github/workflows/rust-automatic-release-and-publish.yml b/.github/workflows/rust-automatic-release-and-publish.yml new file mode 100644 index 0000000000..1d05773d13 --- /dev/null +++ b/.github/workflows/rust-automatic-release-and-publish.yml @@ -0,0 +1,32 @@ +name: Rust Automatic Release and Publish + +# Automatically creates a GitHub release and publishes the latest Rust crate versions to crates.io when a release PR is merged. +on: + pull_request: + branches: + - dev + - main + types: [closed] +jobs: + call-create-release-workflow: + if: github.event.pull_request.merged == true + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-release.yml@dev + with: + changelog-config-path: ./.github/.github_changelog_generator + dev-tag-regex: ^v[0-9]+\.[0-9]+\.[0-9]+-(dev)\.\d*$ + main-tag-regex: ^v[0-9]+\.[0-9]+\.[0-9]+$ + create-github-release: true + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + release: + runs-on: ubuntu-latest + needs: call-create-release-workflow + if: ${{ needs.call-create-release-workflow.outputs.is-release }} + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Dummy Publish to crates.io + # TODO: implement proper publish + run: echo beep boop, pretending to publish \ No newline at end of file diff --git a/.github/workflows/rust-create-release-pr.yml b/.github/workflows/rust-create-release-pr.yml new file mode 100644 index 0000000000..055e5ca9fe --- /dev/null +++ b/.github/workflows/rust-create-release-pr.yml @@ -0,0 +1,44 @@ +name: Rust Create Release PR + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to release Rust under (e.g. `1.2.3`)' + required: true + release-type: + description: Create a `dev` or `main` release. If `dev`, a `dev` postfix and auto-incrementing number will be added automatically (e.g. `1.2.3-dev.x`)' + type: choice + required: true + options: + - dev + - main + +jobs: + create-dev-release-pr: + if: github.event.inputs.release-type == 'dev' + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-create-dev-release-pr.yml@dev + with: + tag-prefix: v + tag-postfix: -dev. + tag-base: ${{ github.event.inputs.version }} + main-tag-regex: ^v[0-9]+\.[0-9]+\.[0-9]+$ + changelog-config-path: ./.github/.github_changelog_generator + release-target: rust + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + create-main-release-pr: + if: github.event.inputs.release-type == 'main' + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-create-main-release-pr.yml@dev + with: + tag-prefix: v + tag-base: ${{ github.event.inputs.version }} + main-tag-regex: ^v[0-9]+\.[0-9]+\.[0-9]+$ + changelog-config-path: ./.github/.github_changelog_generator + release-target: rust + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} \ No newline at end of file diff --git a/.github/workflows/shared-create-dev-release-pr.yml b/.github/workflows/shared-create-dev-release-pr.yml new file mode 100644 index 0000000000..603591ac55 --- /dev/null +++ b/.github/workflows/shared-create-dev-release-pr.yml @@ -0,0 +1,207 @@ +name: Shared / Create Dev Release PR + +# This workflow creates a Pull Request meant for creating `dev` releases. +# In this workflow the version of the `dev` release is determined automatically from a passed in base. +# A changelog, including the new `dev` version, is generated and version strings in relevant files are replaced. +# All these changes are committed and submitted as a Pull Request. + +on: + workflow_call: + inputs: + tag-prefix: + description: "will be pre-pended to tag-base" + required: false + type: string + tag-base: + description: "the base version of the dev release" + required: true + type: string + tag-postfix: + description: "will be appended to tag-base, marks the kind of dev release" + required: true + type: string + main-tag-regex: + description: "the regex to find all related main releases" + required: true + type: string + changelog-path: + description: "path to the changelog file" + required: false + default: ./CHANGELOG.md + type: string + changelog-config-path: + description: "path to the changelog config" + required: true + type: string + pr-body-text: + description: "text to be included in the PR" + required: false + type: string + release-target: + description: "target of the release (rust|wasm)" + required: true + type: string + secrets: + GPG_PRIVATE_KEY: + description: "GPG private key for signing commits and tags" + required: true + GPG_PASSPHRASE: + description: "GPG private passphrase for signing commits and tags" + required: true + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + # Number of commits to fetch. 0 indicates all history for all branches and tags. + fetch-depth: 0 + ref: dev + + - name: Validate version + run: | + VERSION=${{ inputs.tag-prefix }}${{ inputs.tag-base }} + if ! [[ $VERSION =~ ${{ inputs.main-tag-regex }} ]]; then + echo unrecognized version $VERSION, must match ${{ inputs.main-tag-regex }} + exit 1 + fi + + - name: Determine Next Version And Excluded Tags + run: | + + TAG_PREFIX=${{ inputs.tag-prefix }} + TAG_BASE=${{ inputs.tag-base }} + TAG_POSTFIX=${{ inputs.tag-postfix }} + + # joins an array with a delimiter + function join_by { local IFS="$1"; shift; echo "$*"; } + + # takes a string and increments the last number + # e.g. $(updateVersion 1.1.0-dev.1) -> 1.1.0-dev.2 + updateVersion() + { + [[ ${1} =~ ^(.*[^0-9])?([0-9]+)$ ]] && \ + [[ ${#BASH_REMATCH[1]} -gt 0 ]] && \ + printf "%s%0${#BASH_REMATCH[2]}d" "${BASH_REMATCH[1]}" "$((10#${BASH_REMATCH[2]} + 1 ))" || \ + printf "%0${#BASH_REMATCH[2]}d" "$((10#${BASH_REMATCH[2]} + 1))" || \ + printf "${1}" + } + + # create a list of tags that are unrelated to the current release + ALL_TAGS=$(git tag --sort=creatordate -l) + temp_array=() + for value in ${ALL_TAGS[@]} + do + if ! [[ $value == $TAG_PREFIX$TAG_BASE$TAG_POSTFIX* || $value =~ ${{ inputs.main-tag-regex }} ]]; then + temp_array+=($value) + fi + done + UNRELATED_TAGS=$(join_by , "${temp_array[@]}") + unset temp_array + echo UNRELATED_TAGS=$UNRELATED_TAGS + + # determine if there is a previous dev version or this is the first dev release + LATEST_DEV_TAG=$(git tag --list --sort=-version:refname "$TAG_PREFIX$TAG_BASE$TAG_POSTFIX*" | head -n 1) + echo LATEST_DEV_TAG=$LATEST_DEV_TAG + if [[ $LATEST_DEV_TAG == '' ]]; then + NEW_DEV_TAG=$TAG_PREFIX$TAG_BASE$TAG_POSTFIX + NEW_DEV_TAG+="1" + LATEST_DEV_TAG=$NEW_DEV_TAG + FIRST="--exclude-tags " + SECOND=$UNRELATED_TAGS + EXCLUDE_ARG=$FIRST$SECOND + else + NEW_DEV_TAG=$(updateVersion $LATEST_DEV_TAG) + + # exclude dev version already merged in main + ALL_DEV_TAGS_IN_MAIN=$(git tag -l "$TAG_PREFIX$TAG_BASE$TAG_POSTFIX*" --merged $(git log -n 1 refs/remotes/origin/main --pretty=format:"%H")) + temp_array=() + for value in "${ALL_DEV_TAGS_IN_MAIN[@]}" + do + [[ $value != $LATEST_DEV_TAG ]] && temp_array+=($value) + done + FIRST="--exclude-tags " + SECOND=$(join_by , "${temp_array[@]}") + if [[ $SECOND != '' ]]; then + SECOND+=, + fi + THIRD=$UNRELATED_TAGS + unset temp_array + EXCLUDE_ARG=$FIRST$SECOND$THIRD + fi + + # set variables + echo NEW_DEV_TAG=$NEW_DEV_TAG + NEXTVERSION=$NEW_DEV_TAG + + echo NEXTVERSION=$NEXTVERSION + echo NEXTVERSION=$NEXTVERSION >> $GITHUB_ENV + + NEXTVERSION_WITHOUT_PREFIX=$(echo "$NEXTVERSION" | sed "s/$TAG_PREFIX*//") + echo NEXTVERSION_WITHOUT_PREFIX=$NEXTVERSION_WITHOUT_PREFIX + echo NEXTVERSION_WITHOUT_PREFIX=$NEXTVERSION_WITHOUT_PREFIX >> $GITHUB_ENV + + echo EXCLUDE_ARG=$EXCLUDE_ARG + echo EXCLUDE_ARG=$EXCLUDE_ARG >> $GITHUB_ENV + + - name: Run Changelog Generator + uses: './.github/actions/release/changelog-generator' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + changelog-path: ${{ inputs.changelog-path }} + changelog-config-path: ${{ inputs.changelog-config-path }} + future-release: ${{ env.NEXTVERSION }} + optional-arg: ${{env.EXCLUDE_ARG}} + + - name: Check Changelog For Modification + run: | + git add . + if [[ $(git diff --stat --staged) == '' ]]; then + echo 'repository unmodified' + exit 1 + fi + + - name: Import GPG key + id: import-gpg + uses: crazy-max/ghaction-import-gpg@cb4264d3319acaa2bea23d51ef67f80b4f775013 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + git_user_signingkey: true + git_commit_gpgsign: true + git_tag_gpgsign: true + + - name: Bump Versions + uses: './.github/actions/release/bump-versions' + with: + release-target: ${{inputs.release-target}} + version: ${{ env.NEXTVERSION_WITHOUT_PREFIX }} + + - name: Commit changes + run: | + git add . + if [[ $(git diff --stat --staged) == '' ]]; then + echo 'repository unmodified' + exit 1 + fi + git commit -m "changelog and versions" + + - name: Create Pull Request + uses: peter-evans/create-pull-request@67df31e08a133c6a77008b89689677067fef169e + with: + committer: GitHub + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + branch: release/${{ env.NEXTVERSION }} + delete-branch: true + title: 'Release ${{ env.NEXTVERSION }}' + body: | + This automatically generated PR contains changes for the `${{ env.NEXTVERSION }}` version. + ${{inputs.pr-body-text}} + If you discover any mistakes fix them with commits on this branch. If you want to abort the release simply close the PR. + labels: | + No changelog + + + diff --git a/.github/workflows/shared-create-main-release-pr.yml b/.github/workflows/shared-create-main-release-pr.yml new file mode 100644 index 0000000000..30b67006c9 --- /dev/null +++ b/.github/workflows/shared-create-main-release-pr.yml @@ -0,0 +1,152 @@ +name: Shared / Create Main Release PR + +# This workflow creates a Pull Request meant for creating releases. +# A changelog, including the new version, is generated and version strings in relevant files are replaced. +# All these changes are committed and submitted as a Pull Request. + +on: + workflow_call: + inputs: + tag-prefix: + description: "will be prepended to tag-base" + required: false + type: string + tag-base: + description: "the base version of the release" + required: true + type: string + main-tag-regex: + description: "the regex to find all related main releases" + required: true + type: string + changelog-path: + description: "path to the changelog file" + required: false + default: ./CHANGELOG.md + type: string + changelog-config-path: + description: "path to the changelog config" + required: true + type: string + pr-body-text: + description: "text to be included in the PR" + required: false + type: string + release-target: + description: "target of the release (rust|wasm)" + required: true + type: string + secrets: + GPG_PRIVATE_KEY: + description: "GPG private key for signing commits and tags" + required: true + GPG_PASSPHRASE: + description: "GPG private passphrase for signing commits and tags" + required: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + # Number of commits to fetch. 0 indicates all history for all branches and tags. + fetch-depth: 0 + ref: dev + + - name: Validate version + run: | + VERSION=${{ inputs.tag-prefix }}${{ inputs.tag-base }} + if ! [[ $VERSION =~ ${{ inputs.main-tag-regex }} ]]; then + echo unrecognized version $VERSION, must match ${{ inputs.main-tag-regex }} + exit 1 + fi + if [ $(git tag -l "$VERSION") ]; then + echo $VERSION already exists + exit 1 + fi + + - name: Determine Excluded Tags + run: | + + # joins an array with a delimiter + function join_by { local IFS="$1"; shift; echo "$*"; } + + # create a list of tags that are unrelated to the current release + ALL_TAGS=$(git tag -l) + temp_array=() + for value in ${ALL_TAGS[@]} + do + if ! [[ $value =~ ${{ inputs.main-tag-regex }} ]]; then + temp_array+=($value) + fi + done + UNRELATED_TAGS=$(join_by , "${temp_array[@]}") + unset temp_array + echo UNRELATED_TAGS=$UNRELATED_TAGS + + # set variables + FIRST="--exclude-tags " + SECOND=$UNRELATED_TAGS + EXCLUDE_ARG=$FIRST$SECOND + echo EXCLUDE_ARG=$EXCLUDE_ARG + echo EXCLUDE_ARG=$EXCLUDE_ARG >> $GITHUB_ENV + + - name: Run Changelog Generator + uses: './.github/actions/release/changelog-generator' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + changelog-path: ${{ inputs.changelog-path }} + changelog-config-path: ${{ inputs.changelog-config-path }} + future-release: ${{ inputs.tag-prefix }}${{ inputs.tag-base }} + optional-arg: ${{env.EXCLUDE_ARG}} + + - name: Check Changelog For Modification + run: | + git add . + if [[ $(git diff --stat --staged) == '' ]]; then + echo 'repository unmodified' + exit 1 + fi + + - name: Import GPG key + id: import-gpg + uses: crazy-max/ghaction-import-gpg@cb4264d3319acaa2bea23d51ef67f80b4f775013 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + git_user_signingkey: true + git_commit_gpgsign: true + git_tag_gpgsign: true + + - name: Bump Versions + uses: './.github/actions/release/bump-versions' + with: + release-target: ${{inputs.release-target}} + version: ${{ inputs.tag-base }} + + - name: Commit changes + run: | + git add . + if [[ $(git diff --stat --staged) == '' ]]; then + echo 'repository unmodified' + exit 1 + fi + git commit -m "changelog and versions" + + - name: Create Pull Request + uses: peter-evans/create-pull-request@67df31e08a133c6a77008b89689677067fef169e + with: + committer: GitHub + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + branch: release/${{ inputs.tag-prefix }}${{ inputs.tag-base }} + delete-branch: true + title: 'Release ${{ inputs.tag-prefix }}${{ inputs.tag-base }}' + body: | + This automatically generated PR contains changes for the `${{ inputs.tag-prefix }}${{ inputs.tag-base }}` version. + ${{inputs.pr-body-text}} + If you discover any mistakes fix them with commits on this branch. If you want to abort the release simply close the PR. + labels: | + No changelog + diff --git a/.github/workflows/shared-release.yml b/.github/workflows/shared-release.yml new file mode 100644 index 0000000000..0ab62985d9 --- /dev/null +++ b/.github/workflows/shared-release.yml @@ -0,0 +1,136 @@ +name: Shared / Release + +# This workflow creates a GitHub Release. +# It is meant to run after a branch with the pattern `release/VERSION` is merged. +# A changelog, only including the changes in the new version, is generated and used for the GitHub Release. +# The merge commit is tagged with the version from the release branch name. +# This job outputs helpful variables that can be used in the adjacent jobs. +# e.g with ${{ needs.call-create-release-workflow.outputs.is-release }} + + +on: + workflow_call: + inputs: + create-github-release: + description: "controls if a GitHub release should be created" + required: true + type: boolean + changelog-config-path: + description: "path to the changelog config" + required: true + type: string + main-tag-regex: + description: "the regex to find all related main releases" + required: true + type: string + dev-tag-regex: + description: "the regex to find all related dev releases" + required: true + type: string + outputs: + is-release: + description: "is release" + value: ${{ jobs.build.outputs.is-release }} + is-dev-release: + description: "is dev release" + value: ${{ jobs.build.outputs.is-dev-release }} + previous-version: + description: "tag of the previous version" + value: ${{ jobs.build.outputs.is-dev-release }} + current-version: + description: "tag of the current version" + value: ${{ jobs.build.outputs.is-dev-release }} + secrets: + GPG_PRIVATE_KEY: + description: "GPG private key for signing commits and tags" + required: true + GPG_PASSPHRASE: + description: "GPG private passphrase for signing commits and tags" + required: true +jobs: + build: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + outputs: + is-release: ${{ steps.determine-version.outputs.is-release }} + is-dev-release: ${{ steps.determine-version.outputs.is-dev-release }} + previous-version: ${{ steps.determine-version.outputs.previous-version }} + current-version: ${{ steps.determine-version.outputs.current-version }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + # Number of commits to fetch. 0 indicates all history for all branches and tags. + fetch-depth: 0 + + - name: Determine Release Version + id: determine-version + run: | + BRANCHNAME=${{ github.head_ref }} + CURRENT_VERSION=${BRANCHNAME##*/} + if ! [[ $(echo $CURRENT_VERSION | grep -o -P '${{ inputs.dev-tag-regex }}') || $(echo $CURRENT_VERSION | grep -o -P '${{ inputs.main-tag-regex }}') ]]; then + exit 0 + fi + IS_RELEASE=true + echo IS_RELEASE=$IS_RELEASE + echo IS_RELEASE=$IS_RELEASE >> $GITHUB_ENV + echo "::set-output name=is-release::=$IS_RELEASE" + if [[ $(echo $CURRENT_VERSION | grep -w -P '${{ inputs.dev-tag-regex }}') ]]; then + IS_DEV_RELEASE=true + PREVIOUS_VERSION=$(git tag --sort=-committerdate | grep -w -P '${{ inputs.dev-tag-regex }}' | head -n 1) + else + PREVIOUS_VERSION=$(git tag --sort=-committerdate | grep -w -P '${{ inputs.main-tag-regex }}' | head -n 1) + fi + + if [[ $PREVIOUS_VERSION ]]; then + SINCE_ARG="--since-tag $PREVIOUS_VERSION" + fi + + echo IS_DEV_RELEASE=$IS_DEV_RELEASE + echo IS_DEV_RELEASE=$IS_DEV_RELEASE >> $GITHUB_ENV + echo "::set-output name=is-dev-release::=$IS_DEV_RELEASE" + echo CURRENT_VERSION=$CURRENT_VERSION + echo CURRENT_VERSION=$CURRENT_VERSION >> $GITHUB_ENV + echo "::set-output name=current-version::=$CURRENT_VERSION" + echo PREVIOUS_VERSION=$PREVIOUS_VERSION + echo PREVIOUS_VERSION=$PREVIOUS_VERSION >> $GITHUB_ENV + echo "::set-output name=previous-version::=$PREVIOUS_VERSION" + echo SINCE_ARG=$SINCE_ARG + echo SINCE_ARG=$SINCE_ARG >> $GITHUB_ENV + + - name: Import GPG key + if: ${{env.IS_RELEASE}} + id: import-gpg + uses: crazy-max/ghaction-import-gpg@cb4264d3319acaa2bea23d51ef67f80b4f775013 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + git_user_signingkey: true + git_commit_gpgsign: true + git_tag_gpgsign: true + + - name: Tag Release + if: ${{env.IS_RELEASE}} + run: | + git config user.email "${{ steps.import-gpg.outputs.email }}" + git config user.name "${{ steps.import-gpg.outputs.name }}" + git tag -a -m ${{env.CURRENT_VERSION}} ${{env.CURRENT_VERSION}} + git push --follow-tags + + - name: Run Changelog Generator + uses: './.github/actions/release/changelog-generator' + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + changelog-path: RELEASE_CHANGELOG.md + changelog-config-path: ${{ inputs.changelog-config-path }} + future-release: ${{ env.NEXTVERSION }} + optional-arg: ${{ env.SINCE_ARG }} + + - name: Create GitHub release + if: ${{env.IS_RELEASE && inputs.create-github-release}} + uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5 + with: + body_path: RELEASE_CHANGELOG.md + prerelease: ${{env.IS_DEV_RELEASE}} + tag_name: ${{env.CURRENT_VERSION}} + diff --git a/.github/workflows/wasm-automatic-release-and-publish.yml b/.github/workflows/wasm-automatic-release-and-publish.yml new file mode 100644 index 0000000000..d3651aa851 --- /dev/null +++ b/.github/workflows/wasm-automatic-release-and-publish.yml @@ -0,0 +1,35 @@ +name: Wasm Automatic Release and Publish + +# Automatically publishes the latest Wasm bindings version to npm when a release PR is merged. +# Does NOT create a GitHub release. +on: + pull_request: + branches: + - dev + - main + types: [closed] +jobs: + call-create-release-workflow: + if: github.event.pull_request.merged == true + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-release.yml@dev + with: + changelog-config-path: ./bindings/wasm/.github_changelog_generator + dev-tag-regex: ^wasm-v[0-9]+\.[0-9]+\.[0-9]+-(dev)\.\d*$ + main-tag-regex: ^wasm-v[0-9]+\.[0-9]+\.[0-9]+$ + create-github-release: false + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + release: + runs-on: ubuntu-latest + needs: call-create-release-workflow + if: ${{ needs.call-create-release-workflow.outputs.is-release }} + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Release to npm + uses: './.github/actions/publish/publish-wasm' + with: + npm-token: ${{ secrets.NPM_TOKEN }} + tag: ${{ needs.call-create-release-workflow.outputs.is-dev-release && 'dev' }} \ No newline at end of file diff --git a/.github/workflows/wasm-create-release-pr.yml b/.github/workflows/wasm-create-release-pr.yml new file mode 100644 index 0000000000..409f26e3ec --- /dev/null +++ b/.github/workflows/wasm-create-release-pr.yml @@ -0,0 +1,48 @@ +name: Wasm Create Release PR + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to release Wasm under (e.g. `1.2.3`)' + required: true + release-type: + description: Create a `dev` or `main` release. If `dev`, a `dev` postfix and auto-incrementing number will be added automatically (e.g. `1.2.3-dev.x`)' + type: choice + required: true + options: + - dev + - main + +jobs: + create-dev-release-pr: + if: github.event.inputs.release-type == 'dev' + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-create-dev-release-pr.yml@dev + with: + tag-prefix: wasm-v + tag-postfix: -dev. + tag-base: ${{ github.event.inputs.version }} + main-tag-regex: ^wasm-v[0-9]+\.[0-9]+\.[0-9]+$ + changelog-config-path: ./bindings/wasm/.github_changelog_generator + changelog-path: ./bindings/wasm/CHANGELOG.md + pr-body-text: On merge a `dev` release will be published to npm. + release-target: wasm + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + + create-main-release-pr: + if: github.event.inputs.release-type == 'main' + # owner/repository of workflow has to be static, see https://github.community/t/env-variables-in-uses/17466 + uses: iotaledger/identity.rs/.github/workflows/shared-create-main-release-pr.yml@dev + with: + tag-prefix: wasm-v + tag-base: ${{ github.event.inputs.version }} + main-tag-regex: ^wasm-v[0-9]+\.[0-9]+\.[0-9]+$ + changelog-config-path: ./bindings/wasm/.github_changelog_generator + changelog-path: ./bindings/wasm/CHANGELOG.md + release-target: wasm + secrets: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} \ No newline at end of file diff --git a/bindings/wasm/.github_changelog_generator b/bindings/wasm/.github_changelog_generator new file mode 100644 index 0000000000..9144534d29 --- /dev/null +++ b/bindings/wasm/.github_changelog_generator @@ -0,0 +1,15 @@ +issues=true +issues-wo-labels=false +pr-wo-labels=false +author=false +breaking-label=Changed +breaking-labels=Breaking change +enhancement-label=Added +enhancement-labels=Added +bugs-label=Patch +bug-labels=Patch +deprecated-labels=Deprecated +removed-labels=Removed +exclude-labels=Documentation,No changelog +include-labels=Wasm +verbose=true \ No newline at end of file