diff --git a/pull_request_template.md b/.github/pull_request_template.md
similarity index 95%
rename from pull_request_template.md
rename to .github/pull_request_template.md
index cf46729..9729fe6 100644
--- a/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -22,6 +22,5 @@
- [ ] Pull request title follows the format `RNMT-XXXX
`
- [ ] Code follows the code style of this project
-- [ ] CHANGELOG.md file is correctly updated
- [ ] Changes require an update to the documentation
- [ ] Documentation has been updated accordingly
diff --git a/.github/workflows/continuous_integration.yml b/.github/workflows/continuous_integration.yml
index f8047d5..532a9d6 100644
--- a/.github/workflows/continuous_integration.yml
+++ b/.github/workflows/continuous_integration.yml
@@ -25,7 +25,7 @@ jobs:
run: brew link --overwrite swiftlint || brew install swiftlint
- name: Set up XCode
- run: sudo xcode-select --switch /Applications/Xcode_26.0.app
+ run: sudo xcode-select --switch /Applications/Xcode_26.1.1.app/Contents/Developer
- name: Bundle Install
run: bundle install
@@ -42,8 +42,11 @@ jobs:
- name: Setup sonarqube
uses: warchant/setup-sonar-scanner@v8
+ # TODO: Sonarcloud integration is failing, so continue-on-error: true was added
+ # to prevent blocking the pipeline. This should be revisited when we work on fixing this integration.
- name: Send to Sonarcloud
run: bundle exec fastlane sonarqube
+ continue-on-error: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONARCLOUD_KEY }}
diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml
deleted file mode 100644
index 0bb0e48..0000000
--- a/.github/workflows/prepare_release.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-name: Prepare Release
-
-on:
- workflow_dispatch:
- inputs:
- versionBumpLevel:
- description: 'Version bump level (patch, minor, major)'
- required: true
- type: choice
- default: 'patch'
- options:
- - patch
- - minor
- - major
-
-jobs:
- build-and-release:
- if: github.ref == 'refs/heads/main'
- runs-on: macos-15
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: Link SwiftLint or install it
- run: brew link --overwrite swiftlint || brew install swiftlint
-
- - name: Set up XCode
- run: sudo xcode-select --switch /Applications/Xcode_26.0.app
-
- - name: Set up Ruby
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: '3.3'
-
- - name: Bump version
- run: ruby ./scripts/bump_versions.rb ${{ github.event.inputs.versionBumpLevel }}
-
- - name: Build XCFramework
- run: ./scripts/build_framework.sh
-
- - name: Get new version
- id: version
- run: echo "VERSION=$(ruby -e 'puts File.read("./OSInAppBrowserLib.podspec").match(/spec.version.*=.*''(\d+\.\d+\.\d+)''/)[1]')" >> $GITHUB_ENV
-
- - name: Create new branch
- run: |
- git switch --create "prepare-new-release-${{ env.VERSION }}"
-
- - name: Move zip file to root and push changes
- run: |
- if [ -f OSInAppBrowserLib.zip ]; then
- rm OSInAppBrowserLib.zip
- else
- echo "File does not exist."
- fi
- mv build/OSInAppBrowserLib.zip .
- git config --global user.name 'github-actions[bot]'
- git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- git add .
- git commit -m "chore: Bump version to ${{ env.VERSION }}"
- git push origin HEAD:prepare-new-release-${{ env.VERSION }}
-
- - name: Create pull request
- id: create_pr
- run: |
- gh pr create -B main -H prepare-new-release-${{ env.VERSION }} --title 'Prepare `main` to Release `${{ env.VERSION }}`' --body 'Bumps version to `${{ env.VERSION }}`.
Creates an updated and ready-to-be-released `OSInAppBrowserLib.zip`.'
- PR_NUMBER=$(gh pr view --json number --jq '.number')
- echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_ENV
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Add label to the pull request
- run: |
- gh api \
- --method POST \
- -H "Accept: application/vnd.github+json" \
- -H "X-GitHub-Api-Version: 2022-11-28" \
- /repos/${{ github.repository }}/issues/${{ env.PR_NUMBER }}/labels \
- -f "labels[]=release"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..ce9a62e
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,48 @@
+name: Release
+
+on:
+ workflow_dispatch: {}
+
+env:
+ XCODE_VERSION: 26.2
+ NODE_VERSION: '24'
+
+permissions:
+ contents: write
+ packages: write
+
+jobs:
+ release:
+ runs-on: macos-15
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+ token: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v6
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Install dependencies
+ run: |
+ npm i
+
+ - name: Install CocoaPods
+ run: |
+ gem install cocoapods --no-document
+
+ - name: Set Xcode version
+ run: |
+ sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer
+
+ - name: Run semantic-release
+ env:
+ GITHUB_TOKEN: ${{ secrets.CAP_GH_RELEASE_TOKEN }}
+ COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
+ run: |
+ npx semantic-release
+
+
diff --git a/.github/workflows/release_and_publish.yml b/.github/workflows/release_and_publish.yml
deleted file mode 100644
index 12122fb..0000000
--- a/.github/workflows/release_and_publish.yml
+++ /dev/null
@@ -1,67 +0,0 @@
-name: Release and Publish
-
-on:
- pull_request:
- types: [closed]
- branches:
- - 'main'
-
-jobs:
- post-merge:
- if: contains(github.event.pull_request.labels.*.name, 'release') && github.event.pull_request.merged == true
- runs-on: macos-15
-
- steps:
- - name: Checkout Repository
- uses: actions/checkout@v4
-
- - name: Set up Cocoapods
- run: gem install cocoapods
-
- - name: Get new version
- id: version
- run: echo "VERSION=$(ruby -e 'puts File.read("./OSInAppBrowserLib.podspec").match(/spec.version.*=.*''(\d+\.\d+\.\d+)''/)[1]')" >> $GITHUB_ENV
-
- - name: Extract release notes
- run: sh scripts/extract_release_notes.sh "${{ env.VERSION }}" >> release_notes.md
-
- - name: Create Tag
- id: create_tag
- run: |
- # Define the tag name and message
- TAG_NAME="${{ env.VERSION }}"
- TAG_MESSAGE="Tag for version ${{ env.VERSION }}"
-
- # Create the tag
- git tag -a "$TAG_NAME" -m "$TAG_MESSAGE"
- git push origin "$TAG_NAME"
-
- echo "Tag created: $TAG_NAME"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Create Release
- run: |
- # Extract the tag name
- TAG_NAME="${{ env.VERSION }}"
- RELEASE_NOTES="$(cat release_notes.md)"
-
- # Create the release using GitHub CLI
- gh release create "$TAG_NAME" \
- --title "$TAG_NAME" \
- --notes "$RELEASE_NOTES" \
- "OSInAppBrowserLib.zip"
-
- echo "Release created for tag: $TAG_NAME"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Deploy to Cocoapods
- run: pod trunk push ./OSInAppBrowserLib.podspec --allow-warnings
- env:
- COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
-
- - name: Delete Release Branch
- run: git push origin --delete prepare-new-release-${{ env.VERSION }}
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index f289fcd..8115275 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,3 +91,7 @@ iOSInjectionProject/
# macOS
.DS_Store
+
+# Node.js / npm
+node_modules/
+package-lock.json
diff --git a/.releaserc.json b/.releaserc.json
new file mode 100644
index 0000000..58e1147
--- /dev/null
+++ b/.releaserc.json
@@ -0,0 +1,54 @@
+{
+ "branches": ["main"],
+ "tagFormat": "${version}",
+ "plugins": [
+ "@semantic-release/commit-analyzer",
+ "@semantic-release/release-notes-generator",
+ [
+ "@semantic-release/exec",
+ {
+ "prepareCmd": "bash ./scripts/update_xcodeproj_version.sh ${nextRelease.version} \"OSInAppBrowserLib.xcodeproj/project.pbxproj\" && bash ./scripts/update_readme_version.sh ${nextRelease.version} \"OSInAppBrowserLib\" \"README.md\" && bash ./scripts/build_framework.sh \"OSInAppBrowserLib\" \"LICENSE\""
+ }
+ ],
+ "@semantic-release/changelog",
+ [
+ "@semantic-release/npm",
+ {
+ "npmPublish": false
+ }
+ ],
+ [
+ "@semantic-release/git",
+ {
+ "assets": [
+ "CHANGELOG.md",
+ "OSInAppBrowserLib.xcodeproj/project.pbxproj",
+ "OSInAppBrowserLib.podspec",
+ "package.json",
+ "README.md"
+ ],
+ "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
+ }
+ ],
+ [
+ "@semantic-release/github",
+ {
+ "assets": [
+ {
+ "path": "OSInAppBrowserLib.zip",
+ "label": "OSInAppBrowserLib XCFramework"
+ }
+ ],
+ "successComment": false,
+ "failComment": false,
+ "releasedLabels": false
+ }
+ ],
+ [
+ "@semantic-release/exec",
+ {
+ "publishCmd": "bash ./scripts/publish_cocoapods.sh ${nextRelease.version} \"OSInAppBrowserLib\""
+ }
+ ]
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e77bb1f..ace45d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,3 @@
-# Changelog
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
-and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-
## 2.3.1
### Fixes
diff --git a/OSInAppBrowserLib.podspec b/OSInAppBrowserLib.podspec
index 69eaf3a..aec9998 100644
--- a/OSInAppBrowserLib.podspec
+++ b/OSInAppBrowserLib.podspec
@@ -1,8 +1,11 @@
+require 'json'
+package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
+
Pod::Spec.new do |spec|
- spec.name = 'OSInAppBrowserLib'
- spec.version = '2.3.1'
+ spec.name = package['name']
+ spec.version = package['version']
- spec.summary = 'The `OSInAppBrowserLib` is a library that provides a web browser view to load a web page within a Mobile Application.'
+ spec.summary = package['description']
spec.description = <<-DESC
The InAppBrowserLib library behaves as a standard web browser and is useful to load untrusted content without risking your application's security.
@@ -18,8 +21,8 @@ Pod::Spec.new do |spec|
DESC
spec.homepage = 'https://github.com/OutSystems/OSInAppBrowserLib-iOS'
- spec.license = { :type => 'MIT', :file => 'LICENSE' }
- spec.author = { 'OutSystems Mobile Ecosystem' => 'rd.mobileecosystem.team@outsystems.com' }
+ spec.license = { :type => package['license'], :file => 'LICENSE' }
+ spec.author = { package['author'] => package['email'] }
spec.source = { :http => "https://github.com/OutSystems/OSInAppBrowserLib-iOS/releases/download/#{spec.version}/OSInAppBrowserLib.zip", :type => "zip" }
spec.vendored_frameworks = "OSInAppBrowserLib.xcframework"
diff --git a/OSInAppBrowserLib.zip b/OSInAppBrowserLib.zip
deleted file mode 100644
index fb9cb04..0000000
Binary files a/OSInAppBrowserLib.zip and /dev/null differ
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..ac006ff
--- /dev/null
+++ b/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "OSInAppBrowserLib",
+ "version": "2.3.1",
+ "description": "The `OSInAppBrowserLib` is a library that provides a web browser view to load a web page within a Mobile Application.",
+ "author": "OutSystems Mobile Ecosystem",
+ "email": "rd.mobileecosystem.team@outsystems.com",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/OutSystems/OSInAppBrowserLib-iOS.git"
+ },
+ "private": true,
+ "scripts": {
+ "semantic-release": "semantic-release"
+ },
+ "devDependencies": {
+ "@semantic-release/changelog": "^6.0.0",
+ "@semantic-release/commit-analyzer": "^13.0.0",
+ "@semantic-release/exec": "^7.0.0",
+ "@semantic-release/npm": "^13.0.0",
+ "@semantic-release/git": "^10.0.0",
+ "@semantic-release/github": "^12.0.0",
+ "@semantic-release/release-notes-generator": "^14.0.0",
+ "semantic-release": "^25.0.0"
+ }
+}
diff --git a/scripts/build_framework.sh b/scripts/build_framework.sh
index f238a64..4e1b8cc 100755
--- a/scripts/build_framework.sh
+++ b/scripts/build_framework.sh
@@ -1,37 +1,115 @@
-BUILD_FOLDER="build"
-BUILD_SCHEME="OSInAppBrowserLib"
-FRAMEWORK_NAME="OSInAppBrowserLib"
-SIMULATOR_ARCHIVE_PATH="${BUILD_FOLDER}/iphonesimulator.xcarchive"
-IOS_DEVICE_ARCHIVE_PATH="${BUILD_FOLDER}/iphoneos.xcarchive"
+#!/bin/bash
+set -euo pipefail
-rm -rf "${FRAMEWORK_NAME}.zip"
-rm -rf ${BUILD_FOLDER}
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
+source "${SCRIPT_DIR}/common.sh"
+PROJECT_NAME="${1:-}"
+LICENSE_FILE="${2:-}"
+BUILD_DIR="./build"
+
+if [ -z "$PROJECT_NAME" ] || [ -z "$LICENSE_FILE" ]; then
+ log_error "Usage: build_framework.sh "
+ exit 1
+fi
+
+trap 'log_error "Build failed."' ERR
+
+# Validate prerequisites
+check_command "xcodebuild"
+check_file "${PROJECT_NAME}.xcodeproj/project.pbxproj"
+check_file "$LICENSE_FILE"
+
+# Check for optional dependencies
+if ! check_command "xcbeautify"; then
+ log_warning "xcbeautify not found, output will not be formatted"
+ XCBEAUTIFY_CMD="cat"
+else
+ XCBEAUTIFY_CMD="xcbeautify"
+fi
+
+log_info "đ ī¸ Building XCFramework for ${PROJECT_NAME}..."
+
+# Clean build directory
+rm -rf "$BUILD_DIR"
+mkdir -p "$BUILD_DIR"
+
+# Define xcarchive paths
+SIMULATOR_XCARCHIVE="$BUILD_DIR/${PROJECT_NAME}.framework-iphonesimulator.xcarchive"
+DEVICE_XCARCHIVE="$BUILD_DIR/${PROJECT_NAME}.framework-iphoneos.xcarchive"
+
+log_info "đī¸ Building iOS Simulator archive..."
xcodebuild archive \
- -scheme ${BUILD_SCHEME} \
+ -scheme "$PROJECT_NAME" \
-configuration Release \
-destination 'generic/platform=iOS Simulator' \
- -archivePath "./${SIMULATOR_ARCHIVE_PATH}/" \
+ -archivePath "$SIMULATOR_XCARCHIVE" \
SKIP_INSTALL=NO \
- BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
+ BUILD_LIBRARIES_FOR_DISTRIBUTION=YES | ${XCBEAUTIFY_CMD}
+log_info "đī¸ Building iOS Device archive..."
xcodebuild archive \
- -scheme ${BUILD_SCHEME} \
+ -scheme "$PROJECT_NAME" \
-configuration Release \
-destination 'generic/platform=iOS' \
- -archivePath "./${IOS_DEVICE_ARCHIVE_PATH}/" \
+ -archivePath "$DEVICE_XCARCHIVE" \
SKIP_INSTALL=NO \
- BUILD_LIBRARIES_FOR_DISTRIBUTION=YES
+ BUILD_LIBRARIES_FOR_DISTRIBUTION=YES | ${XCBEAUTIFY_CMD}
+
+XCFRAMEWORK_PATH="$BUILD_DIR/${PROJECT_NAME}.xcframework"
+
+# Define framework and dSYM paths
+SIMULATOR_FRAMEWORK="$SIMULATOR_XCARCHIVE/Products/Library/Frameworks/${PROJECT_NAME}.framework"
+SIMULATOR_DSYM="$SIMULATOR_XCARCHIVE/dSYMs/${PROJECT_NAME}.framework.dSYM"
+DEVICE_FRAMEWORK="$DEVICE_XCARCHIVE/Products/Library/Frameworks/${PROJECT_NAME}.framework"
+DEVICE_DSYM="$DEVICE_XCARCHIVE/dSYMs/${PROJECT_NAME}.framework.dSYM"
+
+# Validate that frameworks were created successfully
+if [ ! -d "$SIMULATOR_FRAMEWORK" ]; then
+ log_error "iOS Simulator framework not found: $SIMULATOR_FRAMEWORK"
+ exit 1
+fi
+
+if [ ! -d "$DEVICE_FRAMEWORK" ]; then
+ log_error "iOS Device framework not found: $DEVICE_FRAMEWORK"
+ exit 1
+fi
+
+log_info "đĻ Creating XCFramework..."
+
+# Build xcframework command with conditional dSYM inclusion
+XCFRAMEWORK_ARGS="-framework $SIMULATOR_FRAMEWORK"
+if [ -d "$SIMULATOR_DSYM" ]; then
+ log_info "Including iOS Simulator debug symbols"
+ XCFRAMEWORK_ARGS="$XCFRAMEWORK_ARGS -debug-symbols ${PWD}/$SIMULATOR_DSYM"
+else
+ log_warning "iOS Simulator debug symbols not found, skipping"
+fi
+
+XCFRAMEWORK_ARGS="$XCFRAMEWORK_ARGS -framework $DEVICE_FRAMEWORK"
+if [ -d "$DEVICE_DSYM" ]; then
+ log_info "Including iOS Device debug symbols"
+ XCFRAMEWORK_ARGS="$XCFRAMEWORK_ARGS -debug-symbols ${PWD}/$DEVICE_DSYM"
+else
+ log_warning "iOS Device debug symbols not found, skipping"
+fi
+
+XCFRAMEWORK_ARGS="$XCFRAMEWORK_ARGS -output $XCFRAMEWORK_PATH"
-xcodebuild -create-xcframework \
- -framework "./${SIMULATOR_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework" \
- -debug-symbols "${PWD}/${SIMULATOR_ARCHIVE_PATH}/dSYMs/${FRAMEWORK_NAME}.framework.dSYM" \
- -framework "./${IOS_DEVICE_ARCHIVE_PATH}/Products/Library/Frameworks/${FRAMEWORK_NAME}.framework" \
- -debug-symbols "${PWD}/${IOS_DEVICE_ARCHIVE_PATH}/dSYMs/${FRAMEWORK_NAME}.framework.dSYM" \
- -output "./${BUILD_FOLDER}/${FRAMEWORK_NAME}.xcframework"
+eval "xcodebuild -create-xcframework $XCFRAMEWORK_ARGS"
-cp LICENSE ${BUILD_FOLDER}
+# Validate XCFramework was created successfully
+if [ ! -d "$XCFRAMEWORK_PATH" ]; then
+ log_error "XCFramework creation failed"
+ exit 1
+fi
-cd "./${BUILD_FOLDER}"
+# Create distribution zip
+log_info "đĻ Creating distribution package..."
+LICENSE_BASENAME="$(basename "$LICENSE_FILE")"
+cp "$LICENSE_FILE" "$BUILD_DIR"
+cd "$BUILD_DIR"
+zip -r "${PROJECT_NAME}.zip" "${PROJECT_NAME}.xcframework" "$LICENSE_BASENAME"
+mv "${PROJECT_NAME}.zip" ..
-zip -r "${FRAMEWORK_NAME}.zip" "${FRAMEWORK_NAME}.xcframework" LICENSE
\ No newline at end of file
+log_success "đ XCFramework built successfully: ${PROJECT_NAME}.zip"
diff --git a/scripts/bump_versions.rb b/scripts/bump_versions.rb
deleted file mode 100644
index 0e1c182..0000000
--- a/scripts/bump_versions.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# bump_version.rb
-
-require 'bundler'
-
-# Read version level from ARGV
-level = ARGV[0]
-
-# Define the path to your .podspec file
-podspec_path = "./OSInAppBrowserLib.podspec"
-
-# Read the .podspec file
-podspec_content = File.read(podspec_path)
-
-# Extract current version
-current_version_number = podspec_content.match(/spec.version\s*=\s*["'](\d+\.\d+\.\d+)["']/)[1]
-
-# Parse the version into major, minor, and patch components
-major, minor, patch = current_version_number.split('.').map(&:to_i)
-
-# Increment the version based on the specified level
-case level
-when "major"
- major += 1
- # Reset minor and patch to 0 when major version is incremented
- minor = 0
- patch = 0
-when "minor"
- minor += 1
- # Reset patch to 0 when minor version is incremented
- patch = 0
-when "patch"
- patch += 1
-else
- raise ArgumentError, "Invalid version bump level: #{level}. Must be one of: major, minor, patch."
-end
-
-# Combine the new version components
-new_version_number = [major, minor, patch].join('.')
-
-# Replace 'Unreleased' in the CHANGELOG.md with the new version
-changelog_path = "./CHANGELOG.md"
-changelog_content = File.read(changelog_path)
-new_changelog_content = changelog_content.gsub("[Unreleased]", new_version_number)
-File.write(changelog_path, new_changelog_content)
-
-# Replace the old version with the new version in the .podspec content
-new_podspec_content = podspec_content.gsub(/(spec.version\s*=\s*["'])\d+\.\d+\.\d+(["'])/, "\\1#{new_version_number}\\2")
-File.write(podspec_path, new_podspec_content)
-
-# Set the application name
-LIBRARY_NAME = "OSInAppBrowserLib"
-
-# Set the Xcode project file path
-project_file = "#{LIBRARY_NAME}.xcodeproj/project.pbxproj"
-
-# Read the project file content
-file_content = File.read(project_file)
-
-# Fetch the current MARKETING_VERSION and CURRENT_PROJECT_VERSION values
-current_build_number = Integer(file_content[/CURRENT_PROJECT_VERSION = ([^;]+)/, 1])
-
-# Set the new build numbers
-new_build_number = current_build_number + 1
-
-# Update the MARKETING_VERSION and CURRENT_PROJECT_VERSION values in the project file
-updated_content = file_content.gsub(/MARKETING_VERSION = [^;]+;/, "MARKETING_VERSION = #{new_version_number};")
- .gsub(/CURRENT_PROJECT_VERSION = [^;]+;/, "CURRENT_PROJECT_VERSION = #{new_build_number};")
-
-# Write the updated content back to the project file
-File.open(project_file, "w") { |file| file.puts updated_content }
-
-puts "Version updated to #{new_version_number} (Build Number ##{new_build_number})"
\ No newline at end of file
diff --git a/scripts/common.sh b/scripts/common.sh
new file mode 100755
index 0000000..b9a6758
--- /dev/null
+++ b/scripts/common.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Common utilities for project scripts
+# This file contains shared functions used across multiple scripts
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[1;36m'
+NC='\033[0m' # No Color
+
+# Logging functions with consistent formatting
+log_info() { echo -e "${BLUE}âšī¸ $1${NC}"; }
+log_success() { echo -e "${GREEN}â
$1${NC}"; }
+log_warning() { echo -e "${YELLOW}â ī¸ $1${NC}"; }
+log_error() { echo -e "${RED}â $1${NC}"; }
+
+# Utility functions
+check_command() {
+ if ! command -v "$1" &> /dev/null; then
+ log_error "$1 is required but not installed"
+ return 1
+ fi
+ return 0
+}
+
+check_file() {
+ if [[ ! -f "$1" ]]; then
+ log_error "File not found: $1"
+ return 1
+ fi
+ return 0
+}
+
+check_directory() {
+ if [[ ! -d "$1" ]]; then
+ log_error "Directory not found: $1"
+ return 1
+ fi
+ return 0
+}
diff --git a/scripts/extract_release_notes.sh b/scripts/extract_release_notes.sh
deleted file mode 100644
index 35e03d6..0000000
--- a/scripts/extract_release_notes.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# Check if a section header is provided
-if [ -z "$1" ]; then
- echo "No section header provided. Usage: ./extract_release_notes.sh section_header"
- exit 1
-fi
-
-SECTION_HEADER=$1
-
-# Escape the section header for use in awk
-ESCAPED_HEADER=$(echo "$SECTION_HEADER" | sed 's/[]\/$*.^|[]/\\&/g')
-
-# Extract the specified section from CHANGELOG.md, remove the empty line after the header, and convert ### to #
-awk -v header="$ESCAPED_HEADER" '
- $0 ~ "## " header {flag=1; next}
- flag && /^$/ {next}
- /^## / && !($0 ~ "## " header) {flag=0}
- flag {gsub(/^### /, "# "); print}
-' CHANGELOG.md
diff --git a/scripts/publish_cocoapods.sh b/scripts/publish_cocoapods.sh
new file mode 100755
index 0000000..0214d98
--- /dev/null
+++ b/scripts/publish_cocoapods.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
+source "${SCRIPT_DIR}/common.sh"
+
+VERSION="${1:-}"
+PROJECT_NAME="${2:-}"
+PODSPEC_PATH="${3:-${PROJECT_NAME}.podspec}"
+
+if [ -z "$VERSION" ]; then
+ log_error "No version specified. Usage: publish_cocoapods.sh [podspec_path]"
+ exit 1
+fi
+
+if [ -z "$PROJECT_NAME" ]; then
+ log_error "Usage: publish_cocoapods.sh [podspec_path]"
+ exit 1
+fi
+
+trap 'log_error "Publish failed."' ERR
+
+log_info "Preparing to publish version $VERSION to CocoaPods"
+
+if [ -z "${COCOAPODS_TRUNK_TOKEN:-}" ]; then
+ log_warning "COCOAPODS_TRUNK_TOKEN not set; skipping CocoaPods publish."
+ exit 0
+fi
+
+log_info "Checking if version ${VERSION} already exists on CocoaPods for ${PROJECT_NAME}"
+INFO="$(pod trunk info "${PROJECT_NAME}" 2>/dev/null || true)"
+if echo "$INFO" | grep -E -q "^[[:space:]]*-[[:space:]]+${VERSION}[[:space:]]+\\("; then
+ log_warning "Version ${VERSION} already exists on CocoaPods for ${PROJECT_NAME}; skipping publish."
+ exit 0
+fi
+
+log_info "Running pod trunk push on ${PODSPEC_PATH}"
+pod trunk push "${PODSPEC_PATH}" --allow-warnings --skip-tests
+
+log_success "CocoaPods publish finished"
diff --git a/scripts/update_readme_version.sh b/scripts/update_readme_version.sh
new file mode 100755
index 0000000..2e0725f
--- /dev/null
+++ b/scripts/update_readme_version.sh
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+source "$SCRIPT_DIR/common.sh"
+
+VERSION="${1:-}"
+LIB_NAME="${2:-}"
+README_FILE="${3:-README.md}"
+
+if [ -z "$VERSION" ] || [ -z "$LIB_NAME" ]; then
+ log_error "Usage: update_readme_version.sh [readme_path]"
+ exit 1
+fi
+
+if [ ! -f "$README_FILE" ]; then
+ log_error "README file not found at $README_FILE"
+ exit 1
+fi
+
+log_info "Updating CocoaPods version in $README_FILE..."
+
+# Update the CocoaPods version line in README.md
+# This will match lines like: pod 'LibName', '~> 1.0.1'
+sed -i '' -E "s/(pod '$LIB_NAME', '~> )[0-9]+\.[0-9]+(\.[0-9]+)?'/\1$VERSION'/g" "$README_FILE"
+
+log_success "Updated $LIB_NAME version to $VERSION in $README_FILE"
diff --git a/scripts/update_xcodeproj_version.sh b/scripts/update_xcodeproj_version.sh
new file mode 100755
index 0000000..fa76f71
--- /dev/null
+++ b/scripts/update_xcodeproj_version.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+source "$SCRIPT_DIR/common.sh"
+
+VERSION="${1:-}"
+PBXPROJ="${2:-}"
+
+if [ -z "$VERSION" ] || [ -z "$PBXPROJ" ]; then
+ log_error "Usage: update_xcodeproj_version.sh "
+ exit 1
+fi
+
+if [ ! -f "$PBXPROJ" ]; then
+ log_error "project.pbxproj not found at $PBXPROJ"
+ exit 1
+fi
+
+log_info "Updating MARKETING_VERSION in $PBXPROJ..."
+sed -i '' -E "s/MARKETING_VERSION = [0-9]+\.[0-9]+(\.[0-9]+)?;/MARKETING_VERSION = $VERSION;/g" "$PBXPROJ"
+log_info "Updating CURRENT_PROJECT_VERSION..."
+current_proj_version=$(grep -m1 'CURRENT_PROJECT_VERSION =' "$PBXPROJ" | sed -E 's/.*CURRENT_PROJECT_VERSION = ([0-9]+);/\1/')
+new_proj_version=$((current_proj_version+1))
+sed -i '' -E "s/CURRENT_PROJECT_VERSION = [0-9]+;/CURRENT_PROJECT_VERSION = $new_proj_version;/g" "$PBXPROJ"
+log_success "Bumped MARKETING_VERSION to $VERSION, CURRENT_PROJECT_VERSION to $new_proj_version"