diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c1aae24..95af9c6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -20,5 +20,5 @@ Fixes # - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation -- [ ] I have tested my changes in Obsidian and describte how I tested in [Tests](#tests) +- [ ] I have tested my changes in Obsidian and describe how I tested in [Tests](#tests) - [ ] My code fixes the feature discussed in [Related Issues](#related-issues) if not or not fully describe what is missing in [Missing changes](#missing-changes) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 3e84c14..2dfd983 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -1,18 +1,17 @@ -name: Continuous Deployment +name: Continuous Delivery + on: pull_request: types: - closed branches: - master - workflow_dispatch: jobs: release: runs-on: ubuntu-latest if: github.event.pull_request.merged == true permissions: - pull-requests: write contents: write steps: @@ -20,55 +19,32 @@ jobs: id: checkout uses: actions/checkout@v4 - - name: Use Node.js 18.x - uses: actions/setup-node@v4 - with: - node-version: 18.x - - - name: Install Dependencies - run: npm install + - name: Process Pull Request + id: process-pr + run: | + LABELS=$(jq -r '.pull_request.labels[].name' "$GITHUB_EVENT_PATH") + echo "::debug::Labels: $LABELS" - - name: Bump version - id: version-bump - uses: 4Source/version-control-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - owner: ${{ github.repository_owner }} - repository: ${{ github.event.repository.name }} - pr_number: ${{ github.event.number }} - tag_prefix: '' - dry_run: true + if echo "$LABELS" | grep -q 'major'; then + RELEASE_TYPE_TAG="major" + elif echo "$LABELS" | grep -q 'minor'; then + RELEASE_TYPE_TAG="minor" + elif echo "$LABELS" | grep -q 'patch'; then + RELEASE_TYPE_TAG="patch" + else + echo "::error::No tag found matching a release type." + exit 1 + fi - - name: Configure git - run: | - git config --global user.name "4Source" - git config --global user.email "38220764+4Source@users.noreply.github.com." + echo "Release tag: $RELEASE_TYPE_TAG" + echo "release_type=$RELEASE_TYPE_TAG" >> $GITHUB_OUTPUT - - name: Change version in files - run: | - npm run version -- --new_version=${{ steps.version-bump.outputs.new_version }} - - - name: Commit and push changes + - name: Configure git run: | - git commit -a -m "Apply version ${{ steps.version-bump.outputs.new_version }}" - git push -f + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - - name: Push version tag + - name: Create or Update release type tag run: | - git tag -a ${{ steps.version-bump.outputs.new_version }} -m "${{ steps.version-bump.outputs.new_version }}" - git push -f origin ${{ steps.version-bump.outputs.new_version }} - - - name: Build plugin - run: npm run build - - - name: Create release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - FILES="main.js manifest.json" - if [ -f styles.css ]; then - FILES="$FILES styles.css" - fi - gh release create "${{ steps.version-bump.outputs.new_version }}" \ - --title "${{ steps.version-bump.outputs.new_version }}" \ - --draft $FILES + git tag -fa ${{ steps.process-pr.outputs.release_type }} -m "${{ steps.process-pr.outputs.release_type }}" + git push origin -f ${{ steps.process-pr.outputs.release_type }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13561f1..0d98c3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,18 +2,21 @@ name: Continuous Integration on: pull_request: - branches: - - master + types: + - opened + - synchronize + - reopened + - labeled + - unlabeled paths: - 'src/**' - 'test/**' push: - branches: - - master paths: - 'src/**' - 'test/**' - workflow_dispatch: + branches: + - master jobs: test: @@ -100,8 +103,6 @@ jobs: name: Version Bump runs-on: ubuntu-latest if: github.event_name == 'pull_request' - permissions: - pull-requests: write steps: - name: Checkout @@ -115,4 +116,165 @@ jobs: repository: ${{ github.event.repository.name }} pr_number: ${{ github.event.number }} tag_prefix: '' - dry_run: true \ No newline at end of file + dry_run: true + + beta-release: + name: Beta releases for pull requests + runs-on: ubuntu-latest + needs: + - test + - build + - version + # TODO: Beta releases are currently disabled + if: github.event_name == 'pull_request' && false + + permissions: + pull-requests: write + contents: write + + steps: + - name: Checkout + id: checkout + # TODO: Have to use this commit because fetch-tags is not working in main till this is merged to main + uses: actions/checkout@0548471950d86b19eae6c063105707c831fb5c03 + with: + ref: ${{ github.event.ref }} + fetch-tags: true + + - name: Use Node.js 18.x + uses: actions/setup-node@v4 + with: + node-version: 18.x + + - name: Check changes since last release + id: changes + run: | + echo "skip=false" >> $GITHUB_OUTPUT + + echo "::debug::Tags: git tag --list" + + # Find the latest semver tag + LAST_VERSION_TAG=$(git tag --list | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | grep -v '-' | sort -V | tail -n1 || echo "") + + if [ -z "$LAST_VERSION_TAG" ]; then + echo "No previous tag found. Assuming first release." + else + echo "Last tag: $LAST_VERSION_TAG" + if git diff --quiet "$LAST_VERSION_TAG"..HEAD -- src/; then + echo "No changes in /src since last release." + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + else + echo "::debug::Changes detected in /src since last release." + fi + fi + + # Find the highest release type + if git tag --list | grep -q 'major'; then + RELEASE_TYPE_TAG="major" + elif git tag --list | grep -q 'minor'; then + RELEASE_TYPE_TAG="minor" + elif git tag --list | grep -q 'patch'; then + RELEASE_TYPE_TAG="patch" + else + echo "::error::No tag found matching a release type." + exit 1 + fi + + echo "Release tag: $RELEASE_TYPE_TAG" + echo "release_type=$RELEASE_TYPE_TAG" >> $GITHUB_OUTPUT + + + - name: Install Dependencies + if: ${{ steps.changes.outputs.skip == 'false' }} + run: npm install + + - name: Bump version + if: ${{ steps.changes.outputs.skip == 'false' }} + id: version-bump + uses: 4Source/version-control-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + owner: ${{ github.repository_owner }} + repository: ${{ github.event.repository.name }} + version_increase: ${{ steps.changes.outputs.release_type }} + tag_prefix: '' + dry_run: true + # TODO: Is beta + beta string + + - name: Configure git + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + - name: Change version in files + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + npm run version -- --new_version=${{ steps.version-bump.outputs.new_version }} + git add manifest.json versions.json package.json + + - name: Commit and push changes + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git commit -a -m "Apply version ${{ steps.version-bump.outputs.new_version }}" + git push + + - name: Push version tag + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git tag -a ${{ steps.version-bump.outputs.new_version }} -m "${{ steps.version-bump.outputs.new_version }}" + git push origin ${{ steps.version-bump.outputs.new_version }} + + - name: Build plugin + if: ${{ steps.changes.outputs.skip == 'false' }} + id: build-plugin + run: | + npm run build + + if [ ! -f main.js ]; then + echo "Error: main.js is missing." + exit 1 + fi + + if [ ! -f manifest.json ]; then + echo "Error: manifest.json is missing." + exit 1 + fi + + FILES="main.js manifest.json" + if [ -f styles.css ]; then + FILES="$FILES styles.css" + fi + echo "release_files=$FILES" >> $GITHUB_OUTPUT + + - name: Create release + if: ${{ steps.changes.outputs.skip == 'false' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + FILES="${{ steps.build-plugin.outputs.release_files }}" + gh release create "${{ steps.version-bump.outputs.new_version }}" \ + --title "${{ steps.version-bump.outputs.new_version }}" \ + --generate-notes \ + $FILES + + - name: Remove release type tags + run: | + FAILED=0 + + for tag in major minor patch; do + if [ -n "$(git tag -l "$tag")" ]; then + echo "Deleting remote tag: $tag" + if git push --delete origin $tag; then + echo "::debug::Deleted remote tag $tag" + else + echo "::error::Failed to delete remote tag $tag" + FAILED=1 + fi + else + echo "::debug::No $tag tag found locally." + fi + done + + exit $FAILED diff --git a/.github/workflows/manual_release.yml b/.github/workflows/manual_release.yml deleted file mode 100644 index 464e547..0000000 --- a/.github/workflows/manual_release.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Manual Release -on: - workflow_dispatch: - inputs: - version_increase: - description: 'Level of changes for new version' - required: true - default: 'patch' - type: choice - options: - - patch - - minor - - major - - -jobs: - release: - runs-on: ubuntu-latest - permissions: - pull-requests: write - contents: write - - steps: - - name: Checkout - id: checkout - uses: actions/checkout@v4 - - - name: Use Node.js 18.x - uses: actions/setup-node@v4 - with: - node-version: 18.x - - - name: Install Dependencies - run: npm install - - - name: Bump version - id: version-bump - uses: 4Source/version-control-action@v1 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - owner: ${{ github.repository_owner }} - repository: ${{ github.event.repository.name }} - version_increase: ${{ inputs.version_increase }} - tag_prefix: '' - dry_run: true - - - name: Configure git - run: | - git config --global user.name "4Source" - git config --global user.email "38220764+4Source@users.noreply.github.com." - - - name: Change version in files - run: | - npm run version -- --new_version=${{ steps.version-bump.outputs.new_version }} - git add manifest.json versions.json package.json - - - name: Commit and push changes - run: | - git commit -a -m "Apply version ${{ steps.version-bump.outputs.new_version }}" - git push -f - - - name: Push version tag - run: | - git tag -a ${{ steps.version-bump.outputs.new_version }} -m "${{ steps.version-bump.outputs.new_version }}" - git push -f origin ${{ steps.version-bump.outputs.new_version }} - - - name: Build plugin - run: npm run build - - - name: Create release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - FILES="main.js manifest.json" - if [ -f styles.css ]; then - FILES="$FILES styles.css" - fi - gh release create "${{ steps.version-bump.outputs.new_version }}" \ - --title "${{ steps.version-bump.outputs.new_version }}" \ - --draft $FILES diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5e54775 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,198 @@ +name: Release new plugin version + +on: + workflow_dispatch: + inputs: + selected_release_type: + description: "Choose version update type" + required: true + default: "auto" + type: choice + options: + - auto + - patch + - minor + - major + force_release: + description: "Forces a release even without changes (not auto)" + type: boolean + default: false + + schedule: + # Schedule automatic release every Wednesday + # - cron: "0 0 * * 3" + +jobs: + release: + runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: write + + steps: + - name: Checkout + id: checkout + # TODO: Have to use this commit because fetch-tags is not working in main till this is merged to main + uses: actions/checkout@0548471950d86b19eae6c063105707c831fb5c03 + with: + ref: ${{ github.event.ref }} + fetch-tags: true + + - name: Use Node.js 18.x + uses: actions/setup-node@v4 + with: + node-version: 18.x + + - name: Check changes since last release + id: changes + run: | + echo "skip=false" >> $GITHUB_OUTPUT + + echo "::debug::Tags: git tag --list" + + # Find the latest semver tag + LAST_VERSION_TAG=$(git tag --list | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | grep -v '-' | sort -V | tail -n1 || echo "") + + if [ -z "$LAST_VERSION_TAG" ]; then + echo "No previous tag found. Assuming first release." + else + echo "Last tag: $LAST_VERSION_TAG" + if git diff --quiet "$LAST_VERSION_TAG"..HEAD -- src/; then + if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "::warning::No changes in /src since last release." + FORCE_RELEASE="${{ github.event.inputs.force_release || false }}" + if $FORCE_RELEASE && [ "${{ inputs.selected_release_type }}" != "auto" ]; then + echo "::warning::Forced release." + elif $FORCE_RELEASE && [ "${{ inputs.selected_release_type }}" == "auto" ]; then + echo "::error::Forces is not possible with release type auto." + exit 1 + else + exit 1 + fi + elif [ "${{ github.event_name }}" == "schedule" ]; then + echo "No changes in /src since last release." + echo "skip=true" >> $GITHUB_OUTPUT + exit 0 + fi + else + echo "::debug::Changes detected in /src since last release." + fi + fi + + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "Requested release type: ${{ inputs.selected_release_type }}" + + if [ "${{ inputs.selected_release_type }}" != "auto" ]; then + echo "release_type=${{ inputs.selected_release_type }}" >> $GITHUB_OUTPUT + exit 0 + fi + fi + + # Find the highest release type + if git tag --list | grep -q 'major'; then + RELEASE_TYPE_TAG="major" + elif git tag --list | grep -q 'minor'; then + RELEASE_TYPE_TAG="minor" + elif git tag --list | grep -q 'patch'; then + RELEASE_TYPE_TAG="patch" + else + echo "::error::No tag found matching a release type." + exit 1 + fi + + echo "Release tag: $RELEASE_TYPE_TAG" + echo "release_type=$RELEASE_TYPE_TAG" >> $GITHUB_OUTPUT + + - name: Install Dependencies + if: ${{ steps.changes.outputs.skip == 'false' }} + run: npm install + + - name: Bump version + if: ${{ steps.changes.outputs.skip == 'false' }} + id: version-bump + uses: 4Source/version-control-action@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + owner: ${{ github.repository_owner }} + repository: ${{ github.event.repository.name }} + version_increase: ${{ steps.changes.outputs.release_type }} + tag_prefix: "" + dry_run: true + + - name: Configure git + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + - name: Change version in files + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + npm run version -- --new_version=${{ steps.version-bump.outputs.new_version }} + git add manifest.json versions.json package.json + + - name: Commit and push changes + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git commit -a -m "Apply version ${{ steps.version-bump.outputs.new_version }}" + git push + + - name: Push version tag + if: ${{ steps.changes.outputs.skip == 'false' }} + run: | + git tag -a ${{ steps.version-bump.outputs.new_version }} -m "${{ steps.version-bump.outputs.new_version }}" + git push origin ${{ steps.version-bump.outputs.new_version }} + + - name: Build plugin + if: ${{ steps.changes.outputs.skip == 'false' }} + id: build-plugin + run: | + npm run build + + if [ ! -f main.js ]; then + echo "Error: main.js is missing." + exit 1 + fi + + if [ ! -f manifest.json ]; then + echo "Error: manifest.json is missing." + exit 1 + fi + + FILES="main.js manifest.json" + if [ -f styles.css ]; then + FILES="$FILES styles.css" + fi + echo "release_files=$FILES" >> $GITHUB_OUTPUT + + - name: Create release + if: ${{ steps.changes.outputs.skip == 'false' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + FILES="${{ steps.build-plugin.outputs.release_files }}" + gh release create "${{ steps.version-bump.outputs.new_version }}" \ + --title "${{ steps.version-bump.outputs.new_version }}" \ + --generate-notes \ + $FILES + + - name: Remove release type tags + if: ${{ steps.changes.outputs.skip == 'false'}} + run: | + FAILED=0 + + for tag in major minor patch; do + if [ -n "$(git tag -l "$tag")" ]; then + echo "Deleting remote tag: $tag" + if git push --delete origin $tag; then + echo "::debug::Deleted remote tag $tag" + else + echo "::error::Failed to delete remote tag $tag" + FAILED=1 + fi + else + echo "::debug::No $tag tag found locally." + fi + done + + exit $FAILED diff --git a/README.md b/README.md index a27ef53..569e301 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,6 @@ This is a template repository for [Obsidian](https://obsidian.md) plugins. - minAppVersion (optional) - isDesktopOnly (optional) ### [LICENSE](LICENSE) (optional) -### [.github/workflows/cd.yml](.github/workflows/cd.yml) -versioning > Configure git -``` -git config --global user.name "YOUR-USER" -git config --global user.email "YOUR-EMAIL" -``` ### [bug_report.yaml](.github/ISSUE_TEMPLATE/bug_report.yaml) Plugin Version > Description: The Plugin where to look for the version ### [CONTRIBUTING.md](.github/CONTRIBUTING.md) diff --git a/eslint.config.mjs b/eslint.config.mjs index 563dd65..1c7ca88 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -134,6 +134,18 @@ export default defineConfig([ ignorePattern: 'TODO|HACK|BUG|TEST', applyDefaultIgnorePatterns: false, }], + + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/array-type': ['error', { + default: 'generic' + }], + '@typescript-eslint/ban-ts-comment': ['error', { + minimumDescriptionLength: 10, + 'ts-check': false, + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': false, + 'ts-nocheck': false, + }], }, }, -]); \ No newline at end of file +]); diff --git a/manifest.json b/manifest.json index c4e0825..d15e430 100644 --- a/manifest.json +++ b/manifest.json @@ -7,5 +7,5 @@ "authorUrl": "https://github.com/4Source", "isDesktopOnly": false, "fundingUrl": "https://www.buymeacoffee.com/4Source", - "version": "0.0.1" + "version": "1.1.0" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4e7b42e..821f15a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-plugin-template", - "version": "0.0.1", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-plugin-template", - "version": "0.0.1", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@eslint/eslintrc": "^3.3.1", diff --git a/package.json b/package.json index c9e5dd4..fa57c1b 100644 --- a/package.json +++ b/package.json @@ -35,5 +35,5 @@ "tslib": "2.4.0", "typescript": "^5.9.2" }, - "version": "0.0.1" -} + "version": "1.1.0" +} \ No newline at end of file diff --git a/src/commands/Sample.ts b/src/commands/Sample.ts new file mode 100644 index 0000000..0515bd9 --- /dev/null +++ b/src/commands/Sample.ts @@ -0,0 +1,12 @@ +import { Command } from "obsidian"; +import CurrentPlugin from "../main"; + +export default function (plugin: CurrentPlugin): Command { + return { + id: "sample", + name: "Sample", + callback: () => { + console.log(plugin); + }, + }; +} \ No newline at end of file diff --git a/src/commands/index.ts b/src/commands/index.ts new file mode 100644 index 0000000..6110499 --- /dev/null +++ b/src/commands/index.ts @@ -0,0 +1,8 @@ +import CurrentPlugin from "../main"; +import Sample from "./Sample"; + +export async function addAllCommands(plugin: CurrentPlugin) { + // TODO: Dynamically import all files in the commands folder during bundling time + + plugin.addCommand(Sample(plugin)); +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 80b9ec8..2134251 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import { Plugin } from 'obsidian'; import { DEFAULT_SETTINGS, Settings } from './settings/SettingsInterface'; import { MyPluginSettingTab } from './settings/SettingsTab'; +import { addAllCommands } from './commands'; export default class MyPlugin extends Plugin { settings: Settings; @@ -10,10 +11,13 @@ export default class MyPlugin extends Plugin { // This adds a settings tab so the user can configure various aspects of the plugin this.addSettingTab(new MyPluginSettingTab(this.app, this)); + + // Add all commands registered + addAllCommands(this); } onunload() { - + // TEST CHANGES FOR RELEASE WORKFLOW 6 } async loadSettings() { diff --git a/test/version.test.ts b/test/version.test.ts index 2e293f1..88ec82f 100644 --- a/test/version.test.ts +++ b/test/version.test.ts @@ -1,9 +1,11 @@ import { version as manifestVersion, minAppVersion as manifestMinAppVersion } from '../manifest.json'; import { version as packageVersion } from '../package.json'; +import { version as packageLockVersion } from '../package.json'; import versions from '../versions.json'; test('Versions matching', () => { expect(manifestVersion).toBe(packageVersion); + expect(manifestVersion).toBe(packageLockVersion); expect(Object.keys(versions).find(value => value === manifestVersion)).toBe(manifestVersion); expect(Object.entries(versions).find(value => value[0] === manifestVersion)?.[1]).toBe(manifestMinAppVersion); }); \ No newline at end of file diff --git a/version-change.mjs b/version-change.mjs index c883f31..3307364 100644 --- a/version-change.mjs +++ b/version-change.mjs @@ -1,3 +1,4 @@ +import { execSync } from 'child_process'; import { readFileSync, writeFileSync } from 'fs'; import { valid } from 'semver'; @@ -10,14 +11,14 @@ if (!targetVersion) { throw Error('Param --new_version is empty!'); } if (!valid(targetVersion)) { - throw Error('New version is invalid!'); + throw Error('New version is invalid!') } // read minAppVersion from manifest.json let manifestFile = JSON.parse(readFileSync('manifest.json', 'utf8')); const { minAppVersion } = manifestFile; if (!minAppVersion || minAppVersion === '') { - throw Error('Missing minAppVersion in "manifest.json"'); + throw Error(`Missing minAppVersion in 'manifest.json'`); } // update version to target version @@ -29,7 +30,14 @@ let packageFile = JSON.parse(readFileSync('package.json', 'utf8')); packageFile.version = targetVersion; writeFileSync('package.json', JSON.stringify(packageFile, null, '\t')); -// read versions file +// update version in package-lock +try { + execSync('npm install', { stdio: 'inherit' }); +} catch (error) { + throw Error('npm installed failed: ' + error); +} + +// read versions file let versionsFile = JSON.parse(readFileSync('versions.json', 'utf8')); let keys = Object.keys(versionsFile); diff --git a/versions.json b/versions.json index b5fbc7b..26b14ba 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ { - "0.0.1": "0.15.0" + "1.1.0": "0.15.0" } \ No newline at end of file