diff --git a/.github/actions/draft-release/action.yml b/.github/actions/draft-release/action.yml new file mode 100644 index 0000000..ffc914f --- /dev/null +++ b/.github/actions/draft-release/action.yml @@ -0,0 +1,23 @@ +name: "Draft Release" +description: "Creates or updates a draft release" + +inputs: + branch_name: + description: "The target branch name (1.x, 2.x, etc.)" + required: true + +runs: + using: "composite" + steps: + - name: Draft github release + uses: actions/github-script@v6 + with: + script: | + const script = require('${{ github.action_path }}/script.js') + await script({ + github, + context, + inputs: { + branchName: '${{ inputs.branch_name }}' + } + }) diff --git a/.github/actions/draft-release/script.js b/.github/actions/draft-release/script.js new file mode 100644 index 0000000..511cef3 --- /dev/null +++ b/.github/actions/draft-release/script.js @@ -0,0 +1,43 @@ +module.exports = async ({ github, context, inputs }) => { + const tagName = `unreleased[${inputs.branchName}]`; + const releases = await github.rest.repos.listReleases({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tagName, + }); + + const filtered = releases.data.filter( + (release) => release.draft == true && release.tag_name === tagName, + ); + + if (filtered.length > 0) { + console.log("Deleting old untagged release"); + await github.rest.repos.deleteRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: filtered[0].id, + }); + + try { + console.log(`Deleting old '${tagName}' tag`); + await github.rest.git.deleteRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `tags/${tagName}`, + }); + console.log(`The '${tagName}' tag has been deleted`); + } catch (error) { + console.log(`Tag '${tagName}' does not exist or could not be deleted`); + } + } + + console.log(`Creating a new untagged release for ${inputs.branchName}`); + await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tagName, + name: `Unreleased [${inputs.branchName}]`, + draft: true, + generate_release_notes: true, + }); +}; diff --git a/.github/actions/set-release-tag/action.yml b/.github/actions/set-release-tag/action.yml new file mode 100644 index 0000000..abc6980 --- /dev/null +++ b/.github/actions/set-release-tag/action.yml @@ -0,0 +1,33 @@ +name: "Set Release Tag" +description: "Updates the tag of specific release" + +inputs: + branch_name: + description: "The target branch name (1.x, 2.x, etc.)" + required: true + tag_name: + description: "The target tag name" + required: true + +outputs: + release_id: + description: "The result from the release tag update operation" + value: ${{ steps.set-release-tag.outputs.result }} + +runs: + using: "composite" + steps: + - name: Set release tag + uses: actions/github-script@v6 + id: set-release-tag + with: + script: | + const script = require('${{ github.action_path }}/script.js') + return await script({ + github, + context, + inputs: { + branchName: '${{ inputs.branch_name }}', + tagName: '${{ inputs.tag_name }}' + } + }) diff --git a/.github/actions/set-release-tag/script.js b/.github/actions/set-release-tag/script.js new file mode 100644 index 0000000..1a94707 --- /dev/null +++ b/.github/actions/set-release-tag/script.js @@ -0,0 +1,38 @@ +module.exports = async ({ github, context, inputs }) => { + const releases = await github.rest.repos.listReleases({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: "unreleased", + }); + let release = releases.data.find( + (release) => + release.draft == true && + release.tag_name === `unreleased[${inputs.branchName}]`, + ); + + if (release) { + console.log("Updating the draft release..."); + github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: release.id, + name: inputs.tagName, + tag_name: inputs.tagName, + draft: false, + prerelease: true, + }); + } else { + console.log("Creating a new pre-release..."); + release = github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + name: inputs.tagName, + tag_name: inputs.tagName, + draft: false, + prerelease: true, + generate_release_notes: true, + }); + } + + return release.id; +}; diff --git a/.github/workflows/pull_request.yml b/.github/workflows/ci.yml similarity index 97% rename from .github/workflows/pull_request.yml rename to .github/workflows/ci.yml index 39e22c5..f6178c6 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: CI Validation on: pull_request: branches: - - main + - "[0-9]+.x" defaults: run: diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml deleted file mode 100644 index 8d47532..0000000 --- a/.github/workflows/draft-release.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Draft Release - -on: - push: - branches: - - main - workflow_dispatch: - -concurrency: - group: release - cancel-in-progress: false - -jobs: - draft-release: - name: Draft Github Release - runs-on: ubuntu-20.04 - steps: - - name: Draft github release - uses: actions/github-script@v6 - with: - script: | - const releases = await github.rest.repos.listReleases({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: "unreleased", - }) - const filtered = releases.data.filter(release => release.draft == true && release.tag_name === 'unreleased'); - if (filtered.length === 0) { - console.log("Creating a new untagged release") - await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: "unreleased", - name: "Unreleased", - draft: true, - generate_release_notes: true, - }) - } else { - console.log("Deleting old untagged release") - await github.rest.repos.deleteRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: filtered[0].id - }); - - try { - console.log("Deleting old 'unreleased' tag"); - await github.rest.git.deleteRef({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: 'tags/unreleased' - }); - console.log("Deleted old 'unreleased' tag"); - } catch (error) { - console.log("Tag 'unreleased' does not exist or could not be deleted"); - } - console.log("Creating a new untagged release") - await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: "unreleased", - name: "Unreleased", - draft: true, - generate_release_notes: true, - }) - } diff --git a/.github/workflows/draft_release.yml b/.github/workflows/draft_release.yml new file mode 100644 index 0000000..6052c45 --- /dev/null +++ b/.github/workflows/draft_release.yml @@ -0,0 +1,24 @@ +name: Draft Release +run-name: Draft Release latest updates of ${{ github.ref_name }} (@${{ github.actor }}) + +on: + push: + branches: + - "[0-9]+.x" + +concurrency: + group: release-${{ github.ref_name }} + cancel-in-progress: false + +jobs: + draft-release: + name: Draft Github Release + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Create/Update Draft Release + uses: ./.github/actions/draft-release + with: + branch_name: ${{ github.ref_name }} diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml deleted file mode 100644 index ff01051..0000000 --- a/.github/workflows/pre-release.yml +++ /dev/null @@ -1,197 +0,0 @@ -name: Prerelease - -on: - workflow_dispatch: - inputs: - description: - description: 'Release notes' - type: string - default: '' - required: false - version-update: - description: 'Version update' - required: true - default: 'no update' - type: choice - options: - - major - - minor - - patch - - no update - -env: - NODE_VERSION: "20.16.0" - -concurrency: - group: release - cancel-in-progress: false - -permissions: - contents: write - -jobs: - prerelease: - name: Create prerelease - runs-on: ubuntu-20.04 - outputs: - release_id: ${{ steps.update_release.outputs.result }} - steps: - - name: Get Token - id: get_workflow_token - uses: peter-murray/workflow-application-token-action@v3 - with: - application_id: ${{ vars.GH_MTR_PACKAGE_VERSIONS_APP_ID }} - application_private_key: ${{ secrets.GH_MTR_PACKAGE_VERSIONS_APP_SECRET }} - - - name: Checkout the repo - uses: actions/checkout@v4 - with: - ref: main - lfs: false - token: ${{ steps.get_workflow_token.outputs.token }} - - - name: Install NodeJS - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - registry-url: 'https://registry.npmjs.org' - - - name: Configure github user - run: | - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config user.name "github-actions[bot]" - - - name: Update package version - if: github.event.inputs.version-update != 'no update' - run: | - cd krait-ui - npm version $VERSION_UPDATE --no-git-tag-version - env: - VERSION_UPDATE: ${{ github.event.inputs.version-update }} - - - name: Update the beta version - id: create_tag - env: - GITHUB_TOKEN: ${{ steps.get_workflow_token.outputs.token }} - run: | - cd krait-ui - TAG=$(npm version prerelease --preid=beta) - cd ../ - git commit -am "[GHA] Update package version to $TAG" - git push - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - - - name: Set release tag - id: update_release - uses: actions/github-script@v6 - with: - script: | - const {TAG_NAME, USER, DESCRIPTION} = process.env - const releases = await github.rest.repos.listReleases({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: "unreleased", - }) - const filtered = releases.data.filter(release => release.draft == true && release.tag_name === 'unreleased'); - let release; - if (filtered.length === 0) { - console.log("Creating a new untagged release") - release = await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: "unreleased", - name: "Unreleased", - draft: true, - generate_release_notes: true, - }) - } else { - release = filtered[0]; - } - - let releaseNotes = `${USER} released version ${TAG_NAME}.`; - if (DESCRIPTION) { - releaseNotes += `\n\n Release Notes:\n${DESCRIPTION}`; - } - - github.rest.repos.updateRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: release.id, - name: TAG_NAME, - tag_name: TAG_NAME, - draft: false, - prerelease: true, - body: releaseNotes, - }); - - return release.id - env: - TAG_NAME: ${{ steps.create_tag.outputs.tag }} - USER: ${{ github.event.sender.login }} - DESCRIPTION: ${{ github.event.inputs.description }} - build_ui: - name: Build UI Library - needs: [prerelease] - runs-on: ubuntu-20.04 - steps: - - name: Get Token - id: get_workflow_token - uses: peter-murray/workflow-application-token-action@v3 - with: - application_id: ${{ vars.GH_MTR_PACKAGE_VERSIONS_APP_ID }} - application_private_key: ${{ secrets.GH_MTR_PACKAGE_VERSIONS_APP_SECRET }} - - - name: Checkout the repo - uses: actions/checkout@v4 - with: - ref: main - lfs: false - token: ${{ steps.get_workflow_token.outputs.token }} - - - name: Install NodeJS - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - registry-url: 'https://registry.npmjs.org' - - - name: Retrieve the npm dependencies cache - uses: actions/cache@v4 - id: node-modules-cache - with: - path: node_modules - key: npm-dependencies-${{ runner.os }}-${{ hashFiles('krait-ui/package-lock.json') }} - restore-keys: | - npm-dependencies-${{ hashFiles('krait-ui/package-lock.json') }} - npm-dependencies- - - - name: Install npm dependencies - if: steps.node-modules-cache.outputs.cache-hit != 'true' - run: cd krait-ui && npm ci - - - name: Build FE assets - run: cd krait-ui && npm run build - - - name: Zip the distribution build - run: cd krait-ui && zip -9qry "distribution-package.zip" "./" -i "dist/*" "package.json" "package-lock.json" - - - name: Upload an Asset in GitHub Release - uses: actions/github-script@v6 - with: - script: | - const {RELEASE_ID} = process.env - - const fs = require('fs').promises; - await github.rest.repos.uploadReleaseAsset({ - name: 'distribution-package.zip', - owner: context.repo.owner, - repo: context.repo.repo, - release_id: ${{ env.RELEASE_ID }}, - data: await fs.readFile('./krait-ui/distribution-package.zip') - }); - env: - RELEASE_ID: ${{ needs.prerelease.outputs.release_id }} - - - name: Publish the NPM package - run: cd krait-ui && npm publish --access public --tag dev - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} diff --git a/.github/workflows/pre_release.yml b/.github/workflows/pre_release.yml new file mode 100644 index 0000000..075a1a2 --- /dev/null +++ b/.github/workflows/pre_release.yml @@ -0,0 +1,190 @@ +name: Pre-Release +run-name: Pre-Release ${{ inputs.version-update }} version by @${{ github.actor }} + +on: + workflow_dispatch: + inputs: + version-update: + description: "Version update" + required: true + default: "no update" + type: choice + options: + - minor + - patch + - no update + +env: + NODE_VERSION: "20.16.0" + +concurrency: + group: release + cancel-in-progress: false + +permissions: + contents: write + +jobs: + check_branch: + name: Check the release branch + runs-on: ubuntu-22.04 + outputs: + major_version: ${{ steps.extract_major_version.outputs.version }} + steps: + - name: Check branch name format + run: | + BRANCH_NAME=${GITHUB_REF#refs/heads/} + if ! [[ $BRANCH_NAME =~ ^[0-9]+\.x$ ]]; then + echo "Error: Branch name '$BRANCH_NAME' does not match the required pattern '.x'" + exit 1 + fi + echo "Branch name '$BRANCH_NAME' is valid" + + - name: Extract major version + id: extract_major_version + run: | + BRANCH_NAME=${GITHUB_REF#refs/heads/} + MAJOR_VERSION=$(echo $BRANCH_NAME | sed 's/\.x$//') + echo "version=$MAJOR_VERSION" >> "$GITHUB_OUTPUT" + echo "Extracted major version: $MAJOR_VERSION" + + pre_release: + name: Create Pre-Release + runs-on: ubuntu-22.04 + needs: [check_branch] + outputs: + release_id: ${{ steps.update-release.outputs.release_id }} + steps: + - name: Get Token + id: get_workflow_token + uses: peter-murray/workflow-application-token-action@v3 + with: + application_id: ${{ vars.GH_MTR_PACKAGE_VERSIONS_APP_ID }} + application_private_key: ${{ secrets.GH_MTR_PACKAGE_VERSIONS_APP_SECRET }} + + - name: Checkout the repo + uses: actions/checkout@v4 + with: + ref: main + lfs: false + token: ${{ steps.get_workflow_token.outputs.token }} + + - name: Install NodeJS + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Configure github user + run: | + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + + - name: Ensure that the major version matches the branch + env: + MAJOR_VERSION: ${{ needs.check_branch.outputs.major_version }} + run: | + CURRENT_VERSION=$(node -p "require('./package.json').version") + if [[ "$CURRENT_VERSION" != $MAJOR_VERSION.* ]]; then + npm version $MAJOR_VERSION.0.0 --no-git-tag-version + echo "Updated version to match major version $MAJOR_VERSION" + else + echo "Version already matches major version $MAJOR_VERSION" + fi + + - name: Update version in package.json + working-directory: krait-ui + if: github.event.inputs.version-update != 'no update' + run: npm version $VERSION_UPDATE --no-git-tag-version + env: + VERSION_UPDATE: ${{ github.event.inputs.version-update }} + + - name: Set the version as pre-release(beta) + id: create_tag + working-directory: krait-ui + env: + GITHUB_TOKEN: ${{ steps.get_workflow_token.outputs.token }} + run: | + TAG=$(npm version prerelease --preid=beta) + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + + # - name: Commit the version update + # env: + # TAG_NAME: ${{ steps.create_tag.outputs.tag }} + # run: | + # git commit -am "[GHA] Update package version to $TAG_NAME" + # git push + + - name: Set pre-release tag + id: update-release + uses: ./.github/actions/set-release-tag + with: + # branch_name: ${{ github.ref_name }} + branch_name: 1.x + tag_name: ${{ steps.create_tag.outputs.tag }} + + # build_ui: + # name: Build UI Library + # needs: [pre_release] + # runs-on: ubuntu-20.04 + # steps: + # - name: Get Token + # id: get_workflow_token + # uses: peter-murray/workflow-application-token-action@v3 + # with: + # application_id: ${{ vars.GH_MTR_PACKAGE_VERSIONS_APP_ID }} + # application_private_key: ${{ secrets.GH_MTR_PACKAGE_VERSIONS_APP_SECRET }} + + # - name: Checkout the repo + # uses: actions/checkout@v4 + # with: + # ref: main + # lfs: false + # token: ${{ steps.get_workflow_token.outputs.token }} + + # - name: Install NodeJS + # uses: actions/setup-node@v4 + # with: + # node-version: ${{ env.NODE_VERSION }} + # registry-url: "https://registry.npmjs.org" + + # - name: Retrieve the npm dependencies cache + # uses: actions/cache@v4 + # id: node-modules-cache + # with: + # path: node_modules + # key: npm-dependencies-${{ runner.os }}-${{ hashFiles('krait-ui/package-lock.json') }} + # restore-keys: | + # npm-dependencies-${{ hashFiles('krait-ui/package-lock.json') }} + # npm-dependencies- + + # - name: Install npm dependencies + # if: steps.node-modules-cache.outputs.cache-hit != 'true' + # run: cd krait-ui && npm ci + + # - name: Build FE assets + # run: cd krait-ui && npm run build + + # - name: Zip the distribution build + # run: cd krait-ui && zip -9qry "distribution-package.zip" "./" -i "dist/*" "package.json" "package-lock.json" + + # - name: Upload an Asset in GitHub Release + # uses: actions/github-script@v6 + # with: + # script: | + # const {RELEASE_ID} = process.env + + # const fs = require('fs').promises; + # await github.rest.repos.uploadReleaseAsset({ + # name: 'distribution-package.zip', + # owner: context.repo.owner, + # repo: context.repo.repo, + # release_id: ${{ env.RELEASE_ID }}, + # data: await fs.readFile('./krait-ui/distribution-package.zip') + # }); + # env: + # RELEASE_ID: ${{ needs.prerelease.outputs.release_id }} + + # - name: Publish the NPM package + # run: cd krait-ui && npm publish --access public --tag dev + # env: + # NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} diff --git a/.github/workflows/unpublish-release.yml b/.github/workflows/unpublish-release.yml deleted file mode 100644 index 451d6f2..0000000 --- a/.github/workflows/unpublish-release.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Unpublish Release - -on: - release: - types: [deleted] - -env: - NODE_VERSION: "18.15.0" - -permissions: - contents: write - -jobs: - unpublish_package: - name: Unpublish package - runs-on: ubuntu-20.04 - if: github.event.release.tag_name != 'unreleased' - steps: - - name: Checkout the repo - uses: actions/checkout@v4 - with: - ref: main - lfs: false - - - name: Install NodeJS - uses: actions/setup-node@v4 - with: - node-version: ${{ env.NODE_VERSION }} - registry-url: 'https://registry.npmjs.org' - - - name: Unpublish the NPM package - run: npm unpublish -f @mtrdesign/krait-ui@$VERSION - env: - VERSION: ${{ github.event.release.tag_name }} - NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} - - delete_tag: - name: Delete release tag - runs-on: ubuntu-20.04 - if: github.event.release.tag_name != 'unreleased' - steps: - - name: Checkout the repo - uses: actions/checkout@v4 - with: - ref: main - lfs: false - - - name: Delete the tag - run: git push --delete origin $VERSION - env: - VERSION: ${{ github.event.release.tag_name }}