diff --git a/.github/workflows/beta-release.yaml b/.github/workflows/beta-release.yaml index 9b03b4f..58da22a 100644 --- a/.github/workflows/beta-release.yaml +++ b/.github/workflows/beta-release.yaml @@ -3,27 +3,23 @@ name: Beta Release on: push: branches: - - feature/newopenregister - # - beta + - beta jobs: release-management: runs-on: ubuntu-latest steps: - # Stap 1: Code ophalen - name: Checkout Code uses: actions/checkout@v3 with: fetch-depth: 0 ssh-key: ${{ secrets.DEPLOY_KEY }} - # Stap 2: Stel de appnaam in (gebruik de repo-naam) - name: Set app env run: | echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - # Stap 3: Haal huidige versie uit info.xml, verhoog de patch en voeg beta-suffix toe - name: Get current version and append beta suffix id: increment_version run: | @@ -31,7 +27,7 @@ jobs: git fetch origin main main_version=$(git show origin/main:appinfo/info.xml | grep -oP '(?<=)[^<]+' || echo "") - # Get current version from feature/newopenregister branch + # Get current version from current branch current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") # Split main version into parts @@ -43,7 +39,7 @@ jobs: # Extract beta counter from current version if it exists beta_counter=1 if [[ $current_version =~ -beta\.([0-9]+)$ ]]; then - # If current patch version is still ahead of master, increment counter + # If current patch version is still ahead of main, increment counter current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.(\d+)' | cut -d. -f3) if [ "$current_patch" -eq "$next_patch" ]; then beta_counter=$((BASH_REMATCH[1] + 1)) @@ -58,12 +54,10 @@ jobs: echo "Current version: $current_version" echo "Using beta version: $beta_version" - # Stap 4: Update de versie in info.xml - name: Update version in info.xml run: | sed -i "s|.*|${{ env.NEW_VERSION }}|" appinfo/info.xml - # Stap 5: Commit de nieuwe versie (indien er wijzigingen zijn) - name: Commit version update run: | git config --local user.email "action@github.com" @@ -71,31 +65,26 @@ jobs: git commit -am "Bump beta version to ${{ env.NEW_VERSION }} [skip ci]" git push - # Stap 6: Bereid de signing certificaten voor - name: Prepare Signing Certificate and Key run: | echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key - # Stap 7: Installeer npm dependencies - name: Install npm dependencies uses: actions/setup-node@v3 with: node-version: '18.x' - # Stap 8: Stel PHP in en installeer benodigde extensies - name: Set up PHP and install extensions uses: shivammathur/setup-php@v2 with: php-version: '8.2' extensions: zip, gd - # Stap 9: Voer npm install, build en composer install uit - run: npm ci - run: npm run build - run: composer install --no-dev - # Stap 10: Kopieer de bestanden naar de package directory - name: Copy the package files into the package run: | mkdir -p package/${{ github.event.repository.name }} @@ -137,36 +126,30 @@ jobs: --exclude='.nvmrc' \ ./ package/${{ github.event.repository.name }}/ - # Stap 11: Maak het TAR.GZ archief - name: Create Tarball run: | cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} - # Stap 12: Sign het TAR.GZ bestand met OpenSSL - name: Sign the TAR.GZ file with OpenSSL run: | openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature - # Stap 13: Genereer Git versie informatie (optioneel, voor logging) - name: Git Version id: version uses: codacy/git-version@2.7.1 with: - release-branch: feature/newopenregister + release-branch: beta - # Stap 14: Extraheer repository description (optioneel) - name: Extract repository description id: repo-description run: | description=$(jq -r '.description' <(curl -s https://api.github.com/repos/${{ github.repository }})) echo "REPO_DESCRIPTION=$description" >> $GITHUB_ENV - # Stap 15: Output de versie (voor logging) - name: Use the version run: | echo "Git Version info: ${{ steps.version.outputs.version }}" - # Stap 17: Maak een nieuwe GitHub release (als prerelease) - name: Upload Beta Release uses: ncipollo/release-action@v1.12.0 with: @@ -174,8 +157,8 @@ jobs: name: Beta Release ${{ env.NEW_VERSION }} draft: false prerelease: true + skipIfReleaseExists: true - # Stap 18: Voeg het tarball toe als asset aan de GitHub release - name: Attach tarball to GitHub release uses: svenstaro/upload-release-action@v2 with: @@ -185,7 +168,6 @@ jobs: tag: v${{ env.NEW_VERSION }} overwrite: true - # Stap 19: Upload de app naar de Nextcloud App Store - name: Upload app to Nextcloud appstore uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 with: @@ -195,7 +177,6 @@ jobs: app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} nightly: false - # Stap 20: Verifieer de release - name: Verify version and contents run: | echo "App version: ${{ env.NEW_VERSION }}" diff --git a/.github/workflows/pr-check.yaml b/.github/workflows/pr-check.yaml new file mode 100644 index 0000000..1c264ed --- /dev/null +++ b/.github/workflows/pr-check.yaml @@ -0,0 +1,32 @@ +name: Branch Protection + +on: + pull_request: + branches: + - main + - beta + +jobs: + check-branch: + runs-on: ubuntu-latest + steps: + - name: Check branch + run: | + TARGET="${{ github.base_ref }}" + SOURCE="${{ github.head_ref }}" + + if [[ "$TARGET" == "main" ]]; then + if [[ "$SOURCE" != "beta" ]] && ! [[ "$SOURCE" =~ ^hotfix ]]; then + echo "Error: Pull requests to main must come from 'beta' or a branch starting with 'hotfix'" + echo "Source branch: $SOURCE" + exit 1 + fi + elif [[ "$TARGET" == "beta" ]]; then + if [[ "$SOURCE" != "development" ]] && ! [[ "$SOURCE" =~ ^hotfix ]]; then + echo "Error: Pull requests to beta must come from 'development' or a branch starting with 'hotfix'" + echo "Source branch: $SOURCE" + exit 1 + fi + fi + + echo "Branch check passed: $SOURCE -> $TARGET" diff --git a/.github/workflows/pull-request-from-branch-check.yaml b/.github/workflows/pull-request-from-branch-check.yaml new file mode 100644 index 0000000..1c264ed --- /dev/null +++ b/.github/workflows/pull-request-from-branch-check.yaml @@ -0,0 +1,32 @@ +name: Branch Protection + +on: + pull_request: + branches: + - main + - beta + +jobs: + check-branch: + runs-on: ubuntu-latest + steps: + - name: Check branch + run: | + TARGET="${{ github.base_ref }}" + SOURCE="${{ github.head_ref }}" + + if [[ "$TARGET" == "main" ]]; then + if [[ "$SOURCE" != "beta" ]] && ! [[ "$SOURCE" =~ ^hotfix ]]; then + echo "Error: Pull requests to main must come from 'beta' or a branch starting with 'hotfix'" + echo "Source branch: $SOURCE" + exit 1 + fi + elif [[ "$TARGET" == "beta" ]]; then + if [[ "$SOURCE" != "development" ]] && ! [[ "$SOURCE" =~ ^hotfix ]]; then + echo "Error: Pull requests to beta must come from 'development' or a branch starting with 'hotfix'" + echo "Source branch: $SOURCE" + exit 1 + fi + fi + + echo "Branch check passed: $SOURCE -> $TARGET" diff --git a/.github/workflows/pull-request-lint-check.yaml b/.github/workflows/pull-request-lint-check.yaml new file mode 100644 index 0000000..4a8c874 --- /dev/null +++ b/.github/workflows/pull-request-lint-check.yaml @@ -0,0 +1,21 @@ +name: Lint Check + +on: + pull_request: + branches: + - development + - main + +jobs: + lint-check: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install dependencies + run: npm i + + - name: Linting + run: npm run lint diff --git a/.github/workflows/push-development-to-beta.yaml b/.github/workflows/push-development-to-beta.yaml new file mode 100644 index 0000000..a23f924 --- /dev/null +++ b/.github/workflows/push-development-to-beta.yaml @@ -0,0 +1,44 @@ +name: Create PR to Beta + +permissions: + contents: write + pull-requests: write + +on: + push: + branches: + - development + +jobs: + create-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Create or update PR to beta + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Check if beta branch exists + if ! git ls-remote --heads origin beta | grep -q beta; then + echo "Beta branch does not exist yet. Creating from development..." + git push origin origin/development:refs/heads/beta + fi + + # Check if a PR already exists + EXISTING_PR=$(gh pr list --base beta --head development --state open --json number --jq '.[0].number' || echo "") + + if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then + echo "PR #$EXISTING_PR already exists, it will auto-update with new commits" + else + gh pr create \ + --base beta \ + --head development \ + --title "Release: merge development into beta" \ + --body "Automated PR to sync development changes to beta for beta release. + + Merging this PR will trigger the beta release workflow." + fi diff --git a/.github/workflows/release-beta.yaml b/.github/workflows/release-beta.yaml new file mode 100644 index 0000000..1ee77dc --- /dev/null +++ b/.github/workflows/release-beta.yaml @@ -0,0 +1,170 @@ +name: Beta Release + +on: + push: + branches: + - beta-release + +jobs: + release-management: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Set app env + run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Get current version and append beta suffix + id: increment_version + run: | + git fetch origin main + main_version=$(git show origin/main:appinfo/info.xml | grep -oP '(?<=)[^<]+' || echo "") + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + + IFS='.' read -ra main_version_parts <<< "$main_version" + next_patch=$((main_version_parts[2] + 1)) + + beta_counter=1 + if [[ $current_version =~ -beta\.([0-9]+)$ ]]; then + current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.(\d+)' | cut -d. -f3) + if [ "$current_patch" -eq "$next_patch" ]; then + beta_counter=$((BASH_REMATCH[1] + 1)) + fi + fi + + beta_version="${main_version_parts[0]}.${main_version_parts[1]}.${next_patch}-beta.${beta_counter}" + echo "NEW_VERSION=$beta_version" >> $GITHUB_ENV + echo "new_version=$beta_version" >> $GITHUB_OUTPUT + echo "Main version: $main_version" + echo "Current version: $current_version" + echo "Using beta version: $beta_version" + + - name: Update version in info.xml + run: sed -i "s|.*|${{ env.NEW_VERSION }}|" appinfo/info.xml + + - name: Commit version update + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + if git diff --quiet && git diff --cached --quiet; then + echo "No changes to commit" + else + git add appinfo/info.xml + git commit -m "Bump beta version to ${{ env.NEW_VERSION }} [skip ci]" + git push + fi + + - name: Prepare Signing Certificate and Key + run: | + echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt + echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key + + - name: Install npm dependencies + uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Set up PHP and install extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: zip, gd + + - run: npm ci + - run: npm run build + - run: composer install --no-dev --optimize-autoloader --classmap-authoritative + + - name: Copy the package files into the package + run: | + mkdir -p package/${{ github.event.repository.name }} + rsync -av --progress \ + --exclude='/package' \ + --exclude='/.git' \ + --exclude='/.github' \ + --exclude='/.cursor' \ + --exclude='/.vscode' \ + --exclude='/node_modules' \ + --exclude='/src' \ + --exclude='/tests' \ + --exclude='/package.json' \ + --exclude='/package-lock.json' \ + --exclude='/composer.json' \ + --exclude='/composer.lock' \ + --exclude='/phpcs.xml' \ + --exclude='/phpmd.xml' \ + --exclude='/psalm.xml' \ + --exclude='/phpunit.xml' \ + --exclude='/.phpunit.cache' \ + --exclude='.phpunit.result.cache' \ + --exclude='/jest.config.js' \ + --exclude='/webpack.config.js' \ + --exclude='/tsconfig.json' \ + --exclude='/.babelrc' \ + --exclude='/.eslintrc.js' \ + --exclude='/.prettierrc' \ + --exclude='/stylelint.config.js' \ + --exclude='/.gitignore' \ + --exclude='/.gitattributes' \ + --exclude='/signing-key.key' \ + --exclude='/signing-cert.crt' \ + ./ package/${{ github.event.repository.name }}/ + + - name: Create Tarball + run: cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} + + - name: Sign the TAR.GZ file with OpenSSL + run: openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature + + - name: Upload tarball as artifact + uses: actions/upload-artifact@v4 + with: + name: nextcloud-release-${{ env.NEW_VERSION }} + path: | + nextcloud-release.tar.gz + nextcloud-release.signature + retention-days: 30 + + - name: Git Version + id: version + uses: codacy/git-version@2.7.1 + with: + release-branch: beta-release + + - name: Upload Beta Release + uses: ncipollo/release-action@v1.12.0 + with: + tag: v${{ env.NEW_VERSION }} + name: Beta Release ${{ env.NEW_VERSION }} + draft: false + prerelease: true + skipIfReleaseExists: true + + - name: Attach tarball to GitHub release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: nextcloud-release.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + tag: v${{ env.NEW_VERSION }} + overwrite: true + + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.NEXTCLOUD_APPSTORE_TOKEN }} + download_url: https://github.com/${{ github.repository }}/releases/download/v${{ env.NEW_VERSION }}/${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} + nightly: false + + - name: Verify release + run: | + echo "App version: ${{ env.NEW_VERSION }}" + echo "Tarball contents:" + tar -tvf nextcloud-release.tar.gz | head -50 + echo "info.xml contents:" + tar -xOf nextcloud-release.tar.gz ${{ env.APP_NAME }}/appinfo/info.xml diff --git a/.github/workflows/release-stable.yaml b/.github/workflows/release-stable.yaml new file mode 100644 index 0000000..acf5bbb --- /dev/null +++ b/.github/workflows/release-stable.yaml @@ -0,0 +1,176 @@ +name: Release Workflow + +on: + push: + branches: + - main + workflow_dispatch: + inputs: + version: + description: 'Version to release (leave empty for auto-increment)' + required: false + default: '' + +jobs: + release-management: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Set app env + run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Get current version and increment + id: increment_version + run: | + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml) + IFS='.' read -ra version_parts <<< "$current_version" + ((version_parts[2]++)) + new_version="${version_parts[0]}.${version_parts[1]}.${version_parts[2]}" + echo "NEW_VERSION=$new_version" >> $GITHUB_ENV + echo "new_version=$new_version" >> $GITHUB_OUTPUT + + - name: Update version in info.xml + run: sed -i "s|.*|${{ env.NEW_VERSION }}|" appinfo/info.xml + + - name: Commit version update + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add appinfo/info.xml + git commit -m "Bump version to ${{ env.NEW_VERSION }} [skip ci]" + git push + + - name: Prepare Signing Certificate and Key + run: | + echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt + echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key + + - name: Install npm dependencies + uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Set up PHP and install extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: zip, gd + + - run: npm ci + - run: npm run build + - run: composer install --no-dev --optimize-autoloader --classmap-authoritative + + - name: Copy the package files into the package + run: | + mkdir -p package/${{ github.event.repository.name }} + rsync -av --progress \ + --exclude='/package' \ + --exclude='/.git' \ + --exclude='/.github' \ + --exclude='/.cursor' \ + --exclude='/.vscode' \ + --exclude='/node_modules' \ + --exclude='/src' \ + --exclude='/tests' \ + --exclude='/package.json' \ + --exclude='/package-lock.json' \ + --exclude='/composer.json' \ + --exclude='/composer.lock' \ + --exclude='/phpcs.xml' \ + --exclude='/phpmd.xml' \ + --exclude='/psalm.xml' \ + --exclude='/phpunit.xml' \ + --exclude='/.phpunit.cache' \ + --exclude='.phpunit.result.cache' \ + --exclude='/jest.config.js' \ + --exclude='/webpack.config.js' \ + --exclude='/tsconfig.json' \ + --exclude='/.babelrc' \ + --exclude='/.eslintrc.js' \ + --exclude='/.prettierrc' \ + --exclude='/stylelint.config.js' \ + --exclude='/.gitignore' \ + --exclude='/.gitattributes' \ + --exclude='/signing-key.key' \ + --exclude='/signing-cert.crt' \ + ./ package/${{ github.event.repository.name }}/ + + - name: Create Tarball + run: cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} + + - name: Sign the TAR.GZ file with OpenSSL + run: openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature + + - name: Git Version + id: version + uses: codacy/git-version@2.7.1 + with: + release-branch: main + + - name: Upload Release + uses: ncipollo/release-action@v1.12.0 + with: + tag: v${{ env.NEW_VERSION }} + name: Release ${{ env.NEW_VERSION }} + draft: false + prerelease: false + skipIfReleaseExists: true + + - name: Attach tarball to GitHub release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: nextcloud-release.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + tag: v${{ env.NEW_VERSION }} + overwrite: true + + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.NEXTCLOUD_APPSTORE_TOKEN }} + download_url: https://github.com/${{ github.repository }}/releases/download/v${{ env.NEW_VERSION }}/${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} + nightly: false + + - name: Verify release + run: | + echo "App version: ${{ env.NEW_VERSION }}" + echo "Tarball contents:" + tar -tvf nextcloud-release.tar.gz | head -50 + echo "info.xml contents:" + tar -xOf nextcloud-release.tar.gz ${{ env.APP_NAME }}/appinfo/info.xml + + update-changelog: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set app env + run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Get current version and increment + id: increment_version + run: | + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml) + IFS='.' read -ra version_parts <<< "$current_version" + ((version_parts[2]++)) + new_version="${version_parts[0]}.${version_parts[1]}.${version_parts[2]}" + echo "NEW_VERSION=$new_version" >> $GITHUB_ENV + + - name: Run Changelog CI + if: github.ref == 'refs/heads/main' + uses: saadmk11/changelog-ci@v1.1.2 + with: + persist-credentials: true + release_version: ${{ env.NEW_VERSION }} + config_file: changelog-ci-config.json diff --git a/.github/workflows/release-unstable.yaml b/.github/workflows/release-unstable.yaml new file mode 100644 index 0000000..54b7a36 --- /dev/null +++ b/.github/workflows/release-unstable.yaml @@ -0,0 +1,172 @@ +name: Unstable Release + +on: + push: + branches: + - development-release + +jobs: + release-management: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Set app env + run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Get current version and append unstable suffix + id: increment_version + run: | + git fetch origin main + main_version=$(git show origin/main:appinfo/info.xml | grep -oP '(?<=)[^<]+' || echo "") + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + + IFS='.' read -ra main_version_parts <<< "$main_version" + next_patch=$((main_version_parts[2] + 1)) + + unstable_counter=1 + if [[ $current_version =~ -unstable\.([0-9]+)$ ]]; then + current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+' | cut -d. -f3) + if [ "$current_patch" -eq "$next_patch" ]; then + unstable_counter=$((BASH_REMATCH[1] + 1)) + fi + fi + + unstable_version="${main_version_parts[0]}.${main_version_parts[1]}.${next_patch}-unstable.${unstable_counter}" + echo "NEW_VERSION=$unstable_version" >> $GITHUB_ENV + echo "new_version=$unstable_version" >> $GITHUB_OUTPUT + echo "Main version: $main_version" + echo "Current version: $current_version" + echo "Using unstable version: $unstable_version" + + - name: Update version in info.xml + run: sed -i "s|.*|${{ env.NEW_VERSION }}|" appinfo/info.xml + + - name: Commit version update + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + + # Only commit if there are actual changes + if git diff --quiet && git diff --cached --quiet; then + echo "No changes to commit" + else + git add appinfo/info.xml + git commit -m "Bump unstable version to ${{ env.NEW_VERSION }} [skip ci]" + git push + fi + + - name: Prepare Signing Certificate and Key + run: | + echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt + echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key + + - name: Install npm dependencies + uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Set up PHP and install extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: zip, gd + + - run: npm ci + - run: npm run build + - run: composer install --no-dev --optimize-autoloader --classmap-authoritative + + - name: Copy the package files into the package + run: | + mkdir -p package/${{ github.event.repository.name }} + rsync -av --progress \ + --exclude='/package' \ + --exclude='/.git' \ + --exclude='/.github' \ + --exclude='/.cursor' \ + --exclude='/.vscode' \ + --exclude='/node_modules' \ + --exclude='/src' \ + --exclude='/tests' \ + --exclude='/package.json' \ + --exclude='/package-lock.json' \ + --exclude='/composer.json' \ + --exclude='/composer.lock' \ + --exclude='/phpcs.xml' \ + --exclude='/phpmd.xml' \ + --exclude='/psalm.xml' \ + --exclude='/phpunit.xml' \ + --exclude='/.phpunit.cache' \ + --exclude='.phpunit.result.cache' \ + --exclude='/jest.config.js' \ + --exclude='/webpack.config.js' \ + --exclude='/tsconfig.json' \ + --exclude='/.babelrc' \ + --exclude='/.eslintrc.js' \ + --exclude='/.prettierrc' \ + --exclude='/stylelint.config.js' \ + --exclude='/.gitignore' \ + --exclude='/.gitattributes' \ + --exclude='/signing-key.key' \ + --exclude='/signing-cert.crt' \ + ./ package/${{ github.event.repository.name }}/ + + - name: Create Tarball + run: cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} + + - name: Sign the TAR.GZ file with OpenSSL + run: openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature + + - name: Upload tarball as artifact + uses: actions/upload-artifact@v4 + with: + name: nextcloud-release-${{ env.NEW_VERSION }} + path: | + nextcloud-release.tar.gz + nextcloud-release.signature + retention-days: 30 + + - name: Git Version + id: version + uses: codacy/git-version@2.7.1 + with: + release-branch: development-release + + - name: Upload Unstable Release + uses: ncipollo/release-action@v1.12.0 + with: + tag: v${{ env.NEW_VERSION }} + name: Unstable Release ${{ env.NEW_VERSION }} + draft: false + prerelease: true + skipIfReleaseExists: true + + - name: Attach tarball to GitHub release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: nextcloud-release.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + tag: v${{ env.NEW_VERSION }} + overwrite: true + + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.NEXTCLOUD_APPSTORE_TOKEN }} + download_url: https://github.com/${{ github.repository }}/releases/download/v${{ env.NEW_VERSION }}/${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} + nightly: true + + - name: Verify release + run: | + echo "App version: ${{ env.NEW_VERSION }}" + echo "Tarball contents:" + tar -tvf nextcloud-release.tar.gz | head -50 + echo "info.xml contents:" + tar -xOf nextcloud-release.tar.gz ${{ env.APP_NAME }}/appinfo/info.xml diff --git a/.github/workflows/sync-beta.yaml b/.github/workflows/sync-beta.yaml new file mode 100644 index 0000000..fdac64c --- /dev/null +++ b/.github/workflows/sync-beta.yaml @@ -0,0 +1,60 @@ +name: Sync Beta to Beta-Release + +permissions: + contents: write + actions: write + +on: + push: + branches: + - beta + +jobs: + sync-to-beta-release: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.sha }} + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Configure Git SSH + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + git remote set-url origin git@github.com:${{ github.repository }}.git + + - name: Update beta-release branch + run: | + git fetch origin + + COMMIT_MSG=$(git log -1 --pretty=%B) + + # Preserve existing version on beta-release + BETA_RELEASE_VERSION="" + if git show-ref --quiet refs/remotes/origin/beta-release; then + git checkout origin/beta-release + BETA_RELEASE_VERSION=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + echo "Found existing beta-release version: $BETA_RELEASE_VERSION" + fi + + # Reset or create beta-release from beta + if git show-ref --quiet refs/remotes/origin/beta-release; then + git checkout beta-release + git reset --hard origin/beta + else + git checkout -b beta-release origin/beta + fi + + # Restore preserved version + if [ ! -z "$BETA_RELEASE_VERSION" ]; then + sed -i "s|.*|${BETA_RELEASE_VERSION}|" appinfo/info.xml + git add appinfo/info.xml + git commit -m "${COMMIT_MSG} + + Restored beta-release version to ${BETA_RELEASE_VERSION} [skip ci]" + fi + + git push -f origin beta-release diff --git a/.github/workflows/sync-dev.yaml b/.github/workflows/sync-dev.yaml new file mode 100644 index 0000000..e24e237 --- /dev/null +++ b/.github/workflows/sync-dev.yaml @@ -0,0 +1,59 @@ +name: Sync Development to Development-Release + +permissions: + contents: write + +on: + push: + branches: + - development + +jobs: + sync-to-development-release: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ref: ${{ github.sha }} + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Configure Git SSH + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + git remote set-url origin git@github.com:${{ github.repository }}.git + + - name: Update development-release branch + run: | + git fetch origin + + COMMIT_MSG=$(git log -1 --pretty=%B) + + # Preserve existing version on development-release + DEV_RELEASE_VERSION="" + if git show-ref --quiet refs/remotes/origin/development-release; then + git checkout origin/development-release + DEV_RELEASE_VERSION=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + echo "Found existing development-release version: $DEV_RELEASE_VERSION" + fi + + # Reset or create development-release from development + if git show-ref --quiet refs/remotes/origin/development-release; then + git checkout development-release + git reset --hard origin/development + else + git checkout -b development-release origin/development + fi + + # Restore preserved version + if [ ! -z "$DEV_RELEASE_VERSION" ]; then + sed -i "s|.*|${DEV_RELEASE_VERSION}|" appinfo/info.xml + git add appinfo/info.xml + git commit -m "${COMMIT_MSG} + + Restored development-release version to ${DEV_RELEASE_VERSION}" + fi + + git push -f origin development-release diff --git a/.github/workflows/unstable-release.yaml b/.github/workflows/unstable-release.yaml new file mode 100644 index 0000000..5fcfff9 --- /dev/null +++ b/.github/workflows/unstable-release.yaml @@ -0,0 +1,142 @@ +name: Unstable Release + +on: + push: + branches: + - development + +jobs: + release-management: + runs-on: ubuntu-latest + steps: + + - name: Checkout Code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Set app env + run: | + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Get version from info.xml + id: get_version + run: | + current_version=$(grep -oP '(?<=)[^<]+' appinfo/info.xml || echo "") + echo "NEW_VERSION=$current_version" >> $GITHUB_ENV + echo "new_version=$current_version" >> $GITHUB_OUTPUT + echo "Using version from info.xml: $current_version" + + - name: Prepare Signing Certificate and Key + run: | + echo "${{ secrets.NEXTCLOUD_SIGNING_CERT }}" > signing-cert.crt + echo "${{ secrets.NEXTCLOUD_SIGNING_KEY }}" > signing-key.key + + - name: Install npm dependencies + uses: actions/setup-node@v3 + with: + node-version: '18.x' + + - name: Set up PHP and install extensions + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + extensions: zip, gd + + - run: npm ci + - run: npm run build + - run: composer install --no-dev --optimize-autoloader --classmap-authoritative + + - name: Copy the package files into the package + run: | + mkdir -p package/${{ github.event.repository.name }} + rsync -av --progress \ + --exclude='/package' \ + --exclude='/.git' \ + --exclude='/.github' \ + --exclude='/.cursor' \ + --exclude='/.vscode' \ + --exclude='/node_modules' \ + --exclude='/src' \ + --exclude='/tests' \ + --exclude='/package.json' \ + --exclude='/package-lock.json' \ + --exclude='/composer.json' \ + --exclude='/composer.lock' \ + --exclude='/phpcs.xml' \ + --exclude='/phpmd.xml' \ + --exclude='/psalm.xml' \ + --exclude='/phpunit.xml' \ + --exclude='/.phpunit.cache' \ + --exclude='.phpunit.result.cache' \ + --exclude='/jest.config.js' \ + --exclude='/webpack.config.js' \ + --exclude='/tsconfig.json' \ + --exclude='/.babelrc' \ + --exclude='/.eslintrc.js' \ + --exclude='/.prettierrc' \ + --exclude='/stylelint.config.js' \ + --exclude='/.gitignore' \ + --exclude='/.gitattributes' \ + --exclude='/signing-key.key' \ + --exclude='/signing-cert.crt' \ + ./ package/${{ github.event.repository.name }}/ + + - name: Create Tarball + run: | + cd package && tar -czf ../nextcloud-release.tar.gz ${{ github.event.repository.name }} + + - name: Sign the TAR.GZ file with OpenSSL + run: | + openssl dgst -sha512 -sign signing-key.key nextcloud-release.tar.gz | openssl base64 -out nextcloud-release.signature + + - name: Upload tarball as artifact + uses: actions/upload-artifact@v4 + with: + name: nextcloud-release-${{ env.NEW_VERSION }} + path: | + nextcloud-release.tar.gz + nextcloud-release.signature + retention-days: 30 + + - name: Git Version + id: version + uses: codacy/git-version@2.7.1 + with: + release-branch: development + + - name: Upload Unstable Release + uses: ncipollo/release-action@v1.12.0 + with: + tag: v${{ env.NEW_VERSION }} + name: Unstable Release ${{ env.NEW_VERSION }} + draft: false + prerelease: true + skipIfReleaseExists: true + + - name: Attach tarball to GitHub release + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: nextcloud-release.tar.gz + asset_name: ${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + tag: v${{ env.NEW_VERSION }} + overwrite: true + + - name: Upload app to Nextcloud appstore + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 + with: + app_name: ${{ env.APP_NAME }} + appstore_token: ${{ secrets.NEXTCLOUD_APPSTORE_TOKEN }} + download_url: https://github.com/${{ github.repository }}/releases/download/v${{ env.NEW_VERSION }}/${{ env.APP_NAME }}-${{ env.NEW_VERSION }}.tar.gz + app_private_key: ${{ secrets.NEXTCLOUD_SIGNING_KEY }} + nightly: true + + - name: Verify release + run: | + echo "App version: ${{ env.NEW_VERSION }}" + echo "Tarball contents:" + tar -tvf nextcloud-release.tar.gz | head -50 + echo "info.xml contents:" + tar -xOf nextcloud-release.tar.gz ${{ env.APP_NAME }}/appinfo/info.xml diff --git a/WORKFLOW-UNSTABLE-RELEASE.md b/WORKFLOW-UNSTABLE-RELEASE.md new file mode 100644 index 0000000..18af4a1 --- /dev/null +++ b/WORKFLOW-UNSTABLE-RELEASE.md @@ -0,0 +1,187 @@ +# Unstable Release Workflow - Flow Documentation + +## Overview +This document explains how the unstable release workflow operates when you merge/push to the `development` branch. + +## Complete Flow + +### Step 1: Push to Development Branch +**Trigger:** Developer merges PR or pushes directly to `development` + +**What happens:** +- Changes are committed to `development` branch +- `sync-dev.yaml` workflow is triggered + +--- + +### Step 2: Sync to Development-Release (`sync-dev.yaml`) +**File:** `.github/workflows/sync-dev.yaml` + +**Process:** +1. Fetches all branches from remote +2. **Preserves** the existing version from `development-release` branch (if it exists) + - Example: If `development-release` has `0.1.140-unstable.2`, it stores this +3. Resets `development-release` to match `development` content (all files except version) +4. **Restores** the preserved version back to `appinfo/info.xml` +5. Commits with message: "Restored development-release version to X.X.X-unstable.X" +6. Force pushes to `development-release` + +**Key Point:** This workflow syncs all code changes but keeps the unstable version intact! + +--- + +### Step 3: Release Unstable (`release-unstable.yaml`) +**File:** `.github/workflows/release-unstable.yaml` +**Trigger:** Push to `development-release` branch (from step 2) + +**Version Calculation Logic:** + +```bash +# Example: main = 0.1.139, current = 0.1.138 +main_version = "0.1.139" +current_version = "0.1.138" # or "0.1.140-unstable.1" + +# Calculate next patch from main +next_patch = 139 + 1 = 140 + +# Check if current version already has unstable suffix +if current_version matches "-unstable.X": + extract current_patch from current_version + if current_patch == next_patch: + # Same base version, increment counter + unstable_counter = X + 1 + else: + # Different base version, reset counter + unstable_counter = 1 +else: + # No unstable suffix, start fresh + unstable_counter = 1 + +new_version = "0.1.{next_patch}-unstable.{unstable_counter}" +``` + +**Process:** +1. Fetches `main` branch to get stable version +2. Gets current version from `development-release` +3. Calculates new unstable version (see logic above) +4. Updates `appinfo/info.xml` with new version +5. Commits with `[skip ci]` to prevent infinite loop +6. Pushes version bump back to `development-release` +7. Builds the app (npm, composer) +8. Creates tarball and signs it +9. Creates GitHub prerelease with tag `vX.X.X-unstable.X` +10. Uploads to Nextcloud App Store as nightly build + +--- + +## Version Examples + +### Scenario 1: First Unstable Release +- **Main:** `0.1.139` +- **Current development-release:** `0.1.138` (no unstable suffix) +- **Result:** `0.1.140-unstable.1` ✓ + +### Scenario 2: Incrementing Unstable Counter +- **Main:** `0.1.139` +- **Current development-release:** `0.1.140-unstable.1` +- **Result:** `0.1.140-unstable.2` ✓ + +### Scenario 3: Multiple Increments +- **Main:** `0.1.139` +- **Current development-release:** `0.1.140-unstable.5` +- **Result:** `0.1.140-unstable.6` ✓ + +### Scenario 4: Main Version Bumped +- **Main:** `0.1.140` (was released to main) +- **Current development-release:** `0.1.140-unstable.3` +- **Result:** `0.1.141-unstable.1` ✓ (new series starts) + +--- + +## Key Fixes Applied + +### Fix 1: sync-dev.yaml (Line 56) +**Before:** +```yaml +Restored development-release version to ${DEV_RELEASE_VERSION} [skip ci] +``` + +**After:** +```yaml +Restored development-release version to ${DEV_RELEASE_VERSION} +``` + +**Reason:** Removed `[skip ci]` so the release workflow triggers properly + +--- + +### Fix 2: release-unstable.yaml (Line 33) +**Before:** +```bash +current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.(\d+)' | cut -d. -f3) +``` + +**After:** +```bash +current_patch=$(echo $current_version | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+' | cut -d. -f3) +``` + +**Reason:** The `\d+` pattern doesn't work in grep -P, changed to `[0-9]+` + +--- + +## Testing the Workflow + +To test locally (simulation only, no release): +```powershell +# Set test values +$mainVersion = "0.1.136" +$currentVersion = "0.1.137-unstable.1" + +# Extract parts +$parts = $mainVersion.Split('.') +$nextPatch = [int]$parts[2] + 1 + +# Check for unstable suffix +$unstableCounter = 1 +if ($currentVersion -match '-unstable\.(\d+)$') { + $currentPatch = ($currentVersion -split '\.')[2] -replace '-.*', '' + if ($currentPatch -eq $nextPatch) { + $unstableCounter = [int]$matches[1] + 1 + } +} + +$unstableVersion = "$($parts[0]).$($parts[1]).$nextPatch-unstable.$unstableCounter" +Write-Host "Next version: $unstableVersion" +``` + +--- + +## Important Notes + +1. **[skip ci] is required** in the version bump commit to prevent infinite loop +2. **Version preservation** in sync-dev ensures continuity across syncs +3. **Force push** is safe in sync-dev because development-release is a controlled branch +4. **Prerelease flag** marks GitHub releases as unstable +5. **Nightly flag** marks Nextcloud App Store uploads as development builds + +--- + +## Workflow Dependencies + +``` +development (push) + ↓ +sync-dev.yaml (syncs code, preserves version) + ↓ +development-release (updated) + ↓ +release-unstable.yaml (bumps version, builds, releases) + ↓ +GitHub Release (prerelease) +Nextcloud App Store (nightly) +``` + +--- + +Generated: 2026-02-19 diff --git a/__pycache__/compare_archimate.cpython-38.pyc b/__pycache__/compare_archimate.cpython-38.pyc new file mode 100644 index 0000000..c10b01d Binary files /dev/null and b/__pycache__/compare_archimate.cpython-38.pyc differ diff --git a/appinfo/info.xml b/appinfo/info.xml index 1a78156..be5951a 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -22,7 +22,7 @@ Submit a [bug report](https://github.com/OpenCatalogi/.github/issues/new/choose) Submit a [feature request](https://github.com/OpenCatalogi/.github/issues/new/choose). ]]> - 0.1.137-beta.2 + 0.1.138 agpl organization Conduction @@ -39,6 +39,12 @@ Submit a [feature request](https://github.com/OpenCatalogi/.github/issues/new/ch mysql + + + OCA\SoftwareCatalog\Repair\InitializeSettings + + + OCA\SoftwareCatalog\Cron\OrganizationSync diff --git a/appinfo/routes.php b/appinfo/routes.php index 6eb5e69..5b1a7cd 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -71,6 +71,7 @@ // ArchiMate import/export routes ['name' => 'settings#importArchiMate', 'url' => '/api/archimate/import', 'verb' => 'POST'], ['name' => 'settings#exportArchiMate', 'url' => '/api/archimate/export', 'verb' => 'POST'], + ['name' => 'settings#exportOrgArchiMate', 'url' => '/api/archimate/export/organization/{organizationUuid}', 'verb' => 'GET'], ['name' => 'settings#downloadArchiMate', 'url' => '/api/archimate/download/{fileName}', 'verb' => 'GET'], // ArchiMate status management routes (status reading is via main settings endpoint) @@ -132,6 +133,9 @@ ['name' => 'settings#updateSyncConfig', 'url' => '/api/settings/sync/config', 'verb' => 'POST'], ['name' => 'settings#syncOrganisations', 'url' => '/api/settings/sync/organisations', 'verb' => 'POST'], + // User Profile endpoint + ['name' => 'contactpersonen#getMe', 'url' => '/api/me', 'verb' => 'GET'], + // Contactpersonen Management endpoints ['name' => 'contactpersonen#getContactpersonen', 'url' => '/api/contactpersonen/organisation/{organisationId}', 'verb' => 'GET'], ['name' => 'contactpersonen#getContactPersonsWithUserDetailsForOrganization', 'url' => '/api/contactpersonen/organisation/{organizationUuid}/with-user-details', 'verb' => 'GET'], diff --git a/compare_archimate.py b/compare_archimate.py new file mode 100644 index 0000000..116cf26 --- /dev/null +++ b/compare_archimate.py @@ -0,0 +1,436 @@ +#!/usr/bin/env python3 +""" +ArchiMate XML Semantic Comparison Tool + +Compares two ArchiMate 3.x XML files for structural equivalence: +- Model identifier and name +- Element counts, identifiers, and types +- Relationship counts, identifiers, types, and source/target +- View counts and identifiers +- Organization item counts +- PropertyDefinition counts, identifiers, and names +- Type distribution matching + +Usage: + python3 compare_archimate.py [--json] + +Exit codes: + 0 = all checks passed + 1 = one or more checks failed + 2 = error (file not found, parse error, etc.) +""" + +import sys +import json as json_module +import xml.etree.ElementTree as ET +from collections import Counter + +NS = {"am": "http://www.opengroup.org/xsd/archimate/3.0/"} +XSI = "http://www.w3.org/2001/XMLSchema-instance" + + +def parse_archimate(filepath): + """Parse an ArchiMate XML file and extract structural info.""" + tree = ET.parse(filepath) + root = tree.getroot() + + info = { + "model_id": root.get("identifier", ""), + "model_name": "", + "elements": {}, + "relationships": {}, + "views": {}, + "organizations": [], + "property_definitions": {}, + } + + # Model name + name_el = root.find("am:name", NS) + if name_el is not None: + info["model_name"] = (name_el.text or "").strip() + + # Elements + for el in root.findall(".//am:elements/am:element", NS): + eid = el.get("identifier", "") + etype = el.get(f"{{{XSI}}}type", "") + if eid: + info["elements"][eid] = etype + + # Relationships + for rel in root.findall(".//am:relationships/am:relationship", NS): + rid = rel.get("identifier", "") + rtype = rel.get(f"{{{XSI}}}type", "") + source = rel.get("source", "") + target = rel.get("target", "") + if rid: + info["relationships"][rid] = { + "type": rtype, + "source": source, + "target": target, + } + + # Views (diagrams) + for view in root.findall(".//am:views/am:diagrams/am:view", NS): + vid = view.get("identifier", "") + vname_el = view.find("am:name", NS) + vname = (vname_el.text or "").strip() if vname_el is not None else "" + if vid: + info["views"][vid] = vname + + # Organizations — count all elements recursively. + # ArchiMate organizations use with optional identifierRef (element references) + # or