From 9d1bbc5d9ad259401c42ab1fab41325790cf4202 Mon Sep 17 00:00:00 2001 From: Younes ENNAJI Date: Fri, 21 Feb 2025 19:35:48 +0100 Subject: [PATCH] Wip --- bin/npm | 244 ++++++++++++++++++++++++++++++++--- bin/release | 229 +++++++++++++++++++++++++-------- bin/split | 232 +++++++++++++++++++++++---------- bin/status | 317 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 2 +- 5 files changed, 880 insertions(+), 144 deletions(-) create mode 100755 bin/status diff --git a/bin/npm b/bin/npm index 53860778..2ba12a91 100755 --- a/bin/npm +++ b/bin/npm @@ -1,26 +1,230 @@ #!/usr/bin/env bash -set -e +# Set options +set -o pipefail -NPM_FOLDERS=( - "src/Prime/Resources" - "src/Noty/Prime/Resources" - "src/Notyf/Prime/Resources" - "src/SweetAlert/Prime/Resources" - "src/Toastr/Prime/Resources" +# Define colors and styles +readonly RESET='\033[0m' +readonly BOLD='\033[1m' +readonly DIM='\033[2m' +readonly GREEN='\033[32m' +readonly BLUE='\033[34m' +readonly CYAN='\033[36m' +readonly YELLOW='\033[33m' +readonly RED='\033[31m' + +# Define emoji +readonly ROCKET="šŸš€" +readonly NPM="šŸ“¦" +readonly CHECK="āœ“" +readonly WARN="āš ļø" +readonly ERROR="āŒ" +readonly LOADING="ā³" +readonly SKIP="ā­ļø" + +# Configuration +readonly NPM_PACKAGES=( + "src/Prime/Resources:@flasher/flasher" + "src/Noty/Prime/Resources:@flasher/flasher-noty" + "src/Notyf/Prime/Resources:@flasher/flasher-notyf" + "src/SweetAlert/Prime/Resources:@flasher/flasher-sweetalert" + "src/Toastr/Prime/Resources:@flasher/flasher-toastr" ) -for folder in "${NPM_FOLDERS[@]}"; do - if [ -d "$folder" ]; then - echo "" - echo "Publishing $folder to npm..." - ( - cd "$folder" - npm install - npm version "$VERSION" --no-git-tag-version || true - npm publish --access public - ) - fi -done +# Print functions +print_header() { + echo -e "\n${BOLD}${BLUE}${ROCKET} PHP-Flasher NPM Release ${ROCKET}${RESET}" + echo -e "${DIM}Generated at: $(date -u '+%Y-%m-%d %H:%M:%S') UTC${RESET}" + echo -e "${DIM}By: $(whoami)${RESET}" + echo -e "${DIM}Working Directory: $(pwd)${RESET}\n" +} -echo "Release $VERSION complete – tagged repositories and published packages to npm." +print_section() { + echo -e "\n${BOLD}${CYAN}$1 ${2:-}${RESET}" + echo -e "${DIM}${CYAN}$(printf '%.s─' $(seq 1 50))${RESET}" +} + +success_msg() { + echo -e "${GREEN}${CHECK} $*${RESET}" +} + +info_msg() { + echo -e "${BLUE}${LOADING} $*${RESET}" +} + +warning_msg() { + echo -e "${YELLOW}${WARN} $*${RESET}" +} + +error_msg() { + echo -e "${RED}${ERROR} $*${RESET}" +} + +skip_msg() { + echo -e "${YELLOW}${SKIP} $*${RESET}" +} + +# Check if version exists +check_version_exists() { + local package=$1 + local version=$2 + npm view "${package}@${version}" version >/dev/null 2>&1 +} + +# Validate NPM is installed and logged in +validate_npm() { + print_section "NPM Authentication Check" + + if ! command -v npm >/dev/null 2>&1; then + error_msg "npm is not installed" + return 1 + fi + + if ! npm whoami >/dev/null 2>&1; then + error_msg "You are not logged in to npm. Please run 'npm login' first." + return 1 + fi + + success_msg "Authenticated as $(npm whoami)" + return 0 +} + +# Process a single package +process_package() { + local path_and_name=$1 + local version=$2 + local path="${path_and_name%:*}" + local package="${path_and_name#*:}" + local status=0 + + print_section "Processing ${package}" + + if [ ! -d "$path" ]; then + warning_msg "Directory $path does not exist, skipping..." + return 2 + fi + + info_msg "Checking version ${version}..." + if check_version_exists "$package" "$version"; then + skip_msg "Version ${version} already exists for ${package}, skipping..." + return 0 + fi + + # Use a subshell to prevent directory changes from affecting other iterations + ( + cd "$path" || { + error_msg "Failed to change to directory: $path" + exit 1 + } + + info_msg "Installing dependencies..." + if ! npm install --silent; then + error_msg "Failed to install dependencies" + exit 1 + fi + + info_msg "Updating package version to ${version}..." + npm version "$version" --no-git-tag-version --allow-same-version >/dev/null 2>&1 || true + + info_msg "Publishing ${package}@${version}..." + if npm publish --access public; then + success_msg "Successfully published ${package}@${version}" + exit 0 + else + error_msg "Failed to publish ${package}" + exit 1 + fi + ) + return $? +} + +# Main execution +main() { + if [ "$#" -ne 1 ]; then + echo -e "\n${YELLOW}Usage: $0 ${RESET}" + echo -e "Example: $0 2.1.5\n" + exit 1 + fi + + local VERSION=$1 + VERSION="${VERSION#v}" + + print_header + + # Validate npm authentication + if ! validate_npm; then + error_msg "NPM authentication failed" + exit 1 + fi + + # Track statistics + local start_time=$(date +%s) + local success_count=0 + local failed_count=0 + local skipped_count=0 + local failed_packages=() + local all_failed=true + + # Process each package + for package_info in "${NPM_PACKAGES[@]}"; do + local package_name="${package_info#*:}" + + process_package "$package_info" "$VERSION" + local status=$? + + case $status in + 0) + ((success_count++)) + all_failed=false + ;; + 1) + ((failed_count++)) + failed_packages+=("$package_name") + ;; + 2) + ((skipped_count++)) + all_failed=false + ;; + esac + done + + # Print summary + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + + print_section "Release Summary" + echo -e "Version: ${BOLD}v${VERSION}${RESET}" + echo -e "Duration: ${BOLD}${duration}s${RESET}" + + if [ "$success_count" -gt 0 ]; then + echo -e "Published: ${GREEN}${success_count}${RESET} packages" + fi + + if [ "$skipped_count" -gt 0 ]; then + echo -e "Skipped: ${YELLOW}${skipped_count}${RESET} packages" + fi + + if [ "$failed_count" -gt 0 ]; then + echo -e "Failed: ${RED}${failed_count}${RESET} packages" + echo -e "\nFailed packages:" + for package in "${failed_packages[@]}"; do + echo -e "${RED} - ${package}${RESET}" + done + fi + + if [ "$success_count" -eq 0 ] && [ "$skipped_count" -gt 0 ]; then + success_msg "\nAll packages were already up to date! ${ROCKET}" + elif [ "$all_failed" = true ]; then + error_msg "\nAll package publications failed!" + exit 1 + else + success_msg "\nNPM release completed! ${ROCKET}" + [ "$failed_count" -gt 0 ] && warning_msg "Some packages failed to publish. Check the summary above." + fi + + # Exit with failure if any package failed + [ "$failed_count" -gt 0 ] && exit 1 || exit 0 +} + +# Execute main function +main "$@" diff --git a/bin/release b/bin/release index d576ae27..84d6b997 100755 --- a/bin/release +++ b/bin/release @@ -1,80 +1,199 @@ #!/usr/bin/env bash +# Set options set -e +set -o pipefail -# Make sure the release tag is provided. -if (( "$#" != 1 )) -then - echo "Tag has to be provided." +# Define colors and styles +readonly RESET='\033[0m' +readonly BOLD='\033[1m' +readonly DIM='\033[2m' +readonly ITALIC='\033[3m' +readonly UNDERLINE='\033[4m' +readonly RED='\033[31m' +readonly GREEN='\033[32m' +readonly YELLOW='\033[33m' +readonly BLUE='\033[34m' +readonly MAGENTA='\033[35m' +readonly CYAN='\033[36m' +readonly WHITE='\033[37m' - exit 1 -fi +# Define emoji +readonly CHECK_MARK="āœ“" +readonly CROSS_MARK="āœ—" +readonly INFO_MARK="ℹ" +readonly ARROW_MARK="āžœ" +# Configuration RELEASE_BRANCH="2.x" -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) -VERSION=$1 +VERSION="" +REPOSITORIES=( + "flasher" + "flasher-laravel" + "flasher-symfony" + "flasher-noty" + "flasher-noty-laravel" + "flasher-noty-symfony" + "flasher-notyf" + "flasher-notyf-laravel" + "flasher-notyf-symfony" + "flasher-sweetalert" + "flasher-sweetalert-laravel" + "flasher-sweetalert-symfony" + "flasher-toastr" + "flasher-toastr-laravel" + "flasher-toastr-symfony" +) -# Make sure current branch and release branch match. -if [[ "$RELEASE_BRANCH" != "$CURRENT_BRANCH" ]] -then - echo "Release branch ($RELEASE_BRANCH) does not match the current active branch ($CURRENT_BRANCH)." +# Print functions +print_header() { + echo -e "\n${BOLD}${BLUE}=== PHP-Flasher Release Tool ===${RESET}" + echo -e "${DIM}Running in: $(pwd)${RESET}" + echo -e "${DIM}Date: $(date '+%Y-%m-%d %H:%M:%S')${RESET}\n" +} - exit 1 -fi +print_section() { + echo -e "\n${BOLD}${CYAN}$1${RESET}" + echo -e "${DIM}${CYAN}$(printf '%.s-' $(seq 1 ${#1}))${RESET}\n" +} -# Make sure the working directory is clear. -if [[ ! -z "$(git status --porcelain)" ]] -then - echo "Your working directory is dirty. Did you forget to commit your changes?" +success_msg() { + echo -e "${GREEN}${CHECK_MARK} $*${RESET}" +} - exit 1 -fi +error_msg() { + echo -e "${RED}${CROSS_MARK} Error: $*${RESET}" >&2 +} -# Make sure latest changes are fetched first. -git fetch origin +info_msg() { + echo -e "${BLUE}${INFO_MARK} $*${RESET}" +} -# Make sure that release branch is in sync with origin. -if [[ $(git rev-parse HEAD) != $(git rev-parse origin/$RELEASE_BRANCH) ]] -then - echo "Your branch is out of date with its upstream. Did you forget to pull or push any changes before releasing?" +# Validation functions +validate_args() { + if [ "$#" -ne 1 ]; then + error_msg "Version tag must be provided" + echo -e "\nUsage: $0 " + echo -e "Example: $0 2.1.5\n" + exit 1 + fi - exit 1 -fi + VERSION=$1 + if [[ $VERSION != v* ]]; then + VERSION="v$VERSION" + fi +} -# Always prepend with "v" -if [[ $VERSION != v* ]] -then - VERSION="v$VERSION" -fi +validate_branch() { + local current_branch=$(git rev-parse --abbrev-ref HEAD) + if [[ "$RELEASE_BRANCH" != "$current_branch" ]]; then + error_msg "Release branch ($RELEASE_BRANCH) does not match the current branch ($current_branch)" + exit 1 + fi +} -# Tag PHPFlasher -git tag "$VERSION" -git push origin --tags --force +validate_working_directory() { + if [[ ! -z "$(git status --porcelain)" ]]; then + error_msg "Working directory is not clean. Please commit or stash your changes" + exit 1 + fi +} -# Tag Repositories -for REMOTE in flasher flasher-laravel flasher-symfony \ - flasher-noty flasher-noty-laravel flasher-noty-symfony \ - flasher-notyf flasher-notyf-laravel flasher-notyf-symfony \ - flasher-sweetalert flasher-sweetalert-laravel flasher-sweetalert-symfony \ - flasher-toastr flasher-toastr-laravel flasher-toastr-symfony -do - echo "" - echo "" - echo "Releasing $REMOTE"; +validate_sync() { + git fetch origin > /dev/null 2>&1 + if [[ $(git rev-parse HEAD) != $(git rev-parse origin/$RELEASE_BRANCH) ]]; then + error_msg "Branch is out of sync with origin/$RELEASE_BRANCH" + info_msg "Please pull or push your changes before releasing" + exit 1 + fi +} - TMP_DIR="/tmp/php-flasher" - REMOTE_URL="git@github.com:php-flasher/$REMOTE.git" +# Release function +release_repository() { + local repo=$1 + local tmp_dir="/tmp/php-flasher" + local remote_url="git@github.com:php-flasher/$repo.git" + local start_time=$(date +%s) - rm -rf $TMP_DIR; - mkdir $TMP_DIR; + print_section "Releasing $repo" + # Clean and create temporary directory + rm -rf "$tmp_dir" + mkdir -p "$tmp_dir" + + # Clone and tag repository ( - cd $TMP_DIR; + cd "$tmp_dir" + info_msg "Cloning repository..." + git clone "$remote_url" . > /dev/null 2>&1 - git clone $REMOTE_URL . - git checkout "$RELEASE_BRANCH"; + info_msg "Checking out $RELEASE_BRANCH branch..." + git checkout "$RELEASE_BRANCH" > /dev/null 2>&1 + info_msg "Creating tag $VERSION..." git tag "$VERSION" - git push origin --tags --force + git push origin --tags --force > /dev/null 2>&1 + success_msg "Successfully tagged $repo with $VERSION" ) -done + + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + echo -e "${DIM}Duration: ${duration}s${RESET}\n" +} + +# Main execution +main() { + print_header + + # Validate everything before starting + print_section "Validation" + validate_args "$@" + info_msg "Validating environment..." + validate_branch + validate_working_directory + validate_sync + success_msg "All validations passed" + + # Tag main repository + print_section "Tagging Main Repository" + info_msg "Creating tag $VERSION on main repository..." + git tag "$VERSION" + git push origin --tags --force + success_msg "Main repository tagged successfully" + + # Release all repositories + local total_start_time=$(date +%s) + local success_count=0 + local failed_count=0 + + for repo in "${REPOSITORIES[@]}"; do + if release_repository "$repo"; then + ((success_count++)) + else + ((failed_count++)) + error_msg "Failed to release $repo" + fi + done + + local total_end_time=$(date +%s) + local total_duration=$((total_end_time - total_start_time)) + + # Print summary + print_section "Release Summary" + echo -e "Version: ${BOLD}${VERSION}${RESET}" + echo -e "Total time: ${BOLD}${total_duration}s${RESET}" + echo -e "Successful releases: ${GREEN}${success_count}${RESET}" + if [ "$failed_count" -gt 0 ]; then + echo -e "Failed releases: ${RED}${failed_count}${RESET}" + fi + + if [ "$failed_count" -eq 0 ]; then + success_msg "All repositories released successfully!" + else + error_msg "Some releases failed. Please check the output above." + exit 1 + fi +} + +# Execute main function +main "$@" diff --git a/bin/split b/bin/split index 7099f27a..6a1650ac 100755 --- a/bin/split +++ b/bin/split @@ -1,108 +1,204 @@ #!/usr/bin/env bash -# Set the "errexit" options +# Set options set -o errexit +set -o pipefail -# Define colors and emoji for better visual feedback -INDIGO='\033[0;94m' -GREEN='\033[0;32m' -NC='\033[0m' # No Color -CHECK_MARK="āœ…" -CROSS_MARK="āŒ" +# Define colors and styles +readonly RESET='\033[0m' +readonly BOLD='\033[1m' +readonly DIM='\033[2m' +readonly ITALIC='\033[3m' +readonly UNDERLINE='\033[4m' +readonly RED='\033[31m' +readonly GREEN='\033[32m' +readonly YELLOW='\033[33m' +readonly BLUE='\033[34m' +readonly MAGENTA='\033[35m' +readonly CYAN='\033[36m' +readonly WHITE='\033[37m' + +# Define emoji +readonly CHECK_MARK="āœ“" +readonly CROSS_MARK="āœ—" +readonly INFO_MARK="ℹ" +readonly ARROW_MARK="āžœ" # Initialize global flags DEBUG=0 DRY_RUN=0 # Process command-line arguments -for arg in "$@"; do - case $arg in +while [[ $# -gt 0 ]]; do + case $1 in --debug) - DEBUG=1 - shift - ;; + DEBUG=1 + shift + ;; --dry-run) - DRY_RUN=1 - shift - ;; + DRY_RUN=1 + shift + ;; *) - # Unknown option - ;; + shift + ;; esac done +# Print header function +print_header() { + echo -e "\n${BOLD}${BLUE}=== PHP-Flasher Split Tool ===${RESET}" + echo -e "${DIM}Running in: $(pwd)${RESET}" + echo -e "${DIM}Current branch: $(current_branch)${RESET}" + echo -e "${DIM}Date: $(date '+%Y-%m-%d %H:%M:%S')${RESET}\n" +} + +# Print section header +print_section() { + echo -e "\n${BOLD}${CYAN}$1${RESET}" + echo -e "${DIM}${CYAN}$(printf '%.s-' $(seq 1 ${#1}))${RESET}\n" +} + # Debug message function debug_msg() { if [ "$DEBUG" -eq 1 ]; then - echo -e "${INDIGO}Debug: $*${NC}" + echo -e "${DIM}${MAGENTA}${INFO_MARK} Debug: $*${RESET}" fi } -# Define remotes -REMOTES=( - 'src/Prime:flasher' - 'src/Laravel:flasher-laravel' - 'src/Symfony:flasher-symfony' +# Success message function +success_msg() { + echo -e "${GREEN}${CHECK_MARK} $*${RESET}" +} - 'src/Toastr/Prime:flasher-toastr' - 'src/Toastr/Laravel:flasher-toastr-laravel' - 'src/Toastr/Symfony:flasher-toastr-symfony' +# Error message function +error_msg() { + echo -e "${RED}${CROSS_MARK} Error: $*${RESET}" >&2 +} - 'src/Notyf/Prime:flasher-notyf' - 'src/Notyf/Laravel:flasher-notyf-laravel' - 'src/Notyf/Symfony:flasher-notyf-symfony' - - 'src/SweetAlert/Prime:flasher-sweetalert' - 'src/SweetAlert/Laravel:flasher-sweetalert-laravel' - 'src/SweetAlert/Symfony:flasher-sweetalert-symfony' - - 'src/Noty/Prime:flasher-noty' - 'src/Noty/Laravel:flasher-noty-laravel' - 'src/Noty/Symfony:flasher-noty-symfony' -) +# Info message function +info_msg() { + echo -e "${BLUE}${INFO_MARK} $*${RESET}" +} # Function to get the current git branch name -function current_branch() { +current_branch() { git rev-parse --abbrev-ref HEAD } -# Define a function to split and push code to a remote repository -function split() { - local prefix_and_remote="$1" - local prefix="${prefix_and_remote%:*}" - local remote="${prefix_and_remote#*:}" - local current_branch=$(current_branch) +# Define remotes +declare -A REMOTES=( + # Core packages + ["src/Prime"]="flasher" + ["src/Laravel"]="flasher-laravel" + ["src/Symfony"]="flasher-symfony" - # Add remote if it does not exist (ignoring errors silently) + # Toastr packages + ["src/Toastr/Prime"]="flasher-toastr" + ["src/Toastr/Laravel"]="flasher-toastr-laravel" + ["src/Toastr/Symfony"]="flasher-toastr-symfony" + + # Notyf packages + ["src/Notyf/Prime"]="flasher-notyf" + ["src/Notyf/Laravel"]="flasher-notyf-laravel" + ["src/Notyf/Symfony"]="flasher-notyf-symfony" + + # SweetAlert packages + ["src/SweetAlert/Prime"]="flasher-sweetalert" + ["src/SweetAlert/Laravel"]="flasher-sweetalert-laravel" + ["src/SweetAlert/Symfony"]="flasher-sweetalert-symfony" + + # Noty packages + ["src/Noty/Prime"]="flasher-noty" + ["src/Noty/Laravel"]="flasher-noty-laravel" + ["src/Noty/Symfony"]="flasher-noty-symfony" +) + +# Split function +split() { + local prefix="$1" + local remote="${REMOTES[$prefix]}" + local current_branch=$(current_branch) + local start_time=$(date +%s) + + info_msg "Processing ${BOLD}$remote${RESET} (prefix: ${ITALIC}$prefix${RESET})" + + # Add remote if it doesn't exist if git remote add "$remote" "git@github.com:php-flasher/$remote.git" 2>/dev/null; then - echo -e "${GREEN}Added remote ${INDIGO}$remote${NC} ${CHECK_MARK}" + success_msg "Added remote ${BOLD}$remote${RESET}" else - debug_msg "Remote $remote already exists or could not be added." + debug_msg "Remote $remote already exists" fi - # Split the code using the splitsh-lite utility - SHA1=$(./bin/splitsh-lite --prefix="$prefix") - debug_msg "SHA1 for $prefix is $SHA1." + # Split the code using splitsh-lite + echo -en "${DIM}Splitting code... ${RESET}" + local SHA1=$(./bin/splitsh-lite --prefix="$prefix") + success_msg "Split complete (SHA: ${ITALIC}${SHA1:0:8}${RESET})" - # Push the code to the remote repository on the same branch as the current branch + # Push the code if [ "$DRY_RUN" -eq 0 ]; then - git push "$remote" "$SHA1:refs/heads/$current_branch" -f + echo -en "${DIM}Pushing to remote... ${RESET}" + if git push "$remote" "$SHA1:refs/heads/$current_branch" -f > /dev/null 2>&1; then + success_msg "Pushed to ${BOLD}$remote${RESET} (branch: ${ITALIC}$current_branch${RESET})" + else + error_msg "Failed to push to $remote" + return 1 + fi else - echo -e "${INDIGO}Dry run: Would push $SHA1 to $remote on branch $current_branch${NC}" + info_msg "DRY RUN: Would push ${ITALIC}${SHA1:0:8}${RESET} to ${BOLD}$remote${RESET} (branch: ${ITALIC}$current_branch${RESET})" + fi + + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + echo -e "${DIM}Duration: ${duration}s${RESET}\n" +} + +# Main execution +main() { + print_header + + # Pull latest code + print_section "Updating Repository" + if [ "$DRY_RUN" -eq 0 ]; then + info_msg "Pulling latest code from origin (branch: ${ITALIC}$(current_branch)${RESET})" + git fetch origin "$(current_branch)" > /dev/null 2>&1 + success_msg "Repository updated" + else + info_msg "DRY RUN: Would fetch latest code for branch $(current_branch)" + fi + + # Process splits + print_section "Processing Splits" + local total_start_time=$(date +%s) + local success_count=0 + local failed_count=0 + + for prefix in "${!REMOTES[@]}"; do + if split "$prefix"; then + ((success_count++)) + else + ((failed_count++)) + fi + done + + local total_end_time=$(date +%s) + local total_duration=$((total_end_time - total_start_time)) + + # Print summary + print_section "Summary" + echo -e "Total time: ${BOLD}${total_duration}s${RESET}" + echo -e "Successful splits: ${GREEN}${success_count}${RESET}" + if [ "$failed_count" -gt 0 ]; then + echo -e "Failed splits: ${RED}${failed_count}${RESET}" + fi + + if [ "$failed_count" -eq 0 ]; then + success_msg "All splits completed successfully!" + else + error_msg "Some splits failed. Please check the output above." + exit 1 fi } -# Pull the latest code from the origin repository -if [ "$DRY_RUN" -eq 0 ]; then - echo -e "${INDIGO}Pulling the latest code from the origin repository on branch ${current_branch}...${NC}" - git fetch origin "$current_branch" -else - echo -e "${INDIGO}Dry run: Would fetch latest code for branch $current_branch from the origin repository.${NC}" -fi - -# Iterate over the remotes and split and push the code -for remote in "${REMOTES[@]}"; do - split "$remote" -done - -echo -e "${GREEN}All done!${NC} ${CHECK_MARK}" +# Execute main function +main diff --git a/bin/status b/bin/status new file mode 100755 index 00000000..c5463424 --- /dev/null +++ b/bin/status @@ -0,0 +1,317 @@ +#!/usr/bin/env bash + +# Set options +set -e +set -o pipefail + +# Define colors and styles +readonly RESET='\033[0m' +readonly BOLD='\033[1m' +readonly DIM='\033[2m' +readonly ITALIC='\033[3m' +readonly UNDERLINE='\033[4m' +readonly RED='\033[31m' +readonly GREEN='\033[32m' +readonly YELLOW='\033[33m' +readonly BLUE='\033[34m' +readonly MAGENTA='\033[35m' +readonly CYAN='\033[36m' +readonly WHITE='\033[37m' + +# Define emoji +readonly ROCKET="šŸš€" +readonly PACKAGE="šŸ“¦" +readonly CALENDAR="šŸ“…" +readonly CLOCK="šŸ•’" +readonly INFO="ā„¹ļø" +readonly WARNING="āš ļø" +readonly CHECK="āœ“" +readonly BRANCH="🌿" +readonly TAG="šŸ·ļø" +readonly GITHUB="⭐" +readonly STAR="⭐" +readonly NPM="šŸ“¦" +readonly PACKAGIST="šŸŽÆ" + +# Configuration +readonly ORGANIZATION="php-flasher" +readonly MAIN_BRANCH="2.x" +readonly REPOSITORIES=( + "flasher" + "flasher-laravel" + "flasher-symfony" + "flasher-noty" + "flasher-noty-laravel" + "flasher-noty-symfony" + "flasher-notyf" + "flasher-notyf-laravel" + "flasher-notyf-symfony" + "flasher-sweetalert" + "flasher-sweetalert-laravel" + "flasher-sweetalert-symfony" + "flasher-toastr" + "flasher-toastr-laravel" + "flasher-toastr-symfony" +) + +# Print functions +print_header() { + echo -e "\n${BOLD}${BLUE}${ROCKET} PHP-Flasher Status Dashboard ${ROCKET}${RESET}" + echo -e "${DIM}Generated on: $(date '+%Y-%m-%d %H:%M:%S %Z')${RESET}" + echo -e "${DIM}By: $(git config user.name) <$(git config user.email)>${RESET}" + echo -e "${DIM}Working Directory: $(pwd)${RESET}\n" +} + +print_section() { + echo -e "\n${BOLD}${CYAN}$1 ${2:-}${RESET}" + echo -e "${DIM}${CYAN}$(printf '%.s─' $(seq 1 50))${RESET}" +} + +success_msg() { + echo -e "${GREEN}${CHECK} $*${RESET}" +} + +warning_msg() { + echo -e "${YELLOW}${WARNING} $*${RESET}" +} + +info_msg() { + echo -e "${BLUE}${INFO} $*${RESET}" +} + +# Get the latest tag for a repository +get_latest_tag() { + local repo=$1 + git ls-remote --tags --refs "git@github.com:${ORGANIZATION}/${repo}.git" | + sort -t '/' -k 3 -V | + tail -n1 | + awk -F/ '{print $3}' +} + +# Get commit count since last tag +get_commit_count_since_tag() { + local repo=$1 + local tag=$2 + git rev-list "${tag}..HEAD" --count 2>/dev/null || echo "0" +} + +# Get repository statistics +get_repo_stats() { + local repo=$1 + local tmp_dir="/tmp/php-flasher-status/${repo}" + + mkdir -p "$tmp_dir" + if [ ! -d "$tmp_dir/.git" ]; then + git clone -q "git@github.com:${ORGANIZATION}/${repo}.git" "$tmp_dir" 2>/dev/null + fi + + ( + cd "$tmp_dir" + git fetch -q origin 2>/dev/null + echo "$(git rev-parse --short HEAD)|$(git rev-parse --abbrev-ref HEAD)|$(git log -1 --format='%cr')|$(git log -1 --format='%s')" + ) +} + +# Check composer.json version +check_composer_version() { + local file="composer.json" + if [ -f "$file" ]; then + grep -o '"version": *"[^"]*"' "$file" 2>/dev/null | cut -d'"' -f4 || echo "N/A" + else + echo "N/A" + fi +} + +# Add curl with proper user agent for API calls +curl_cmd() { + # You can set your GitHub token as an environment variable + local gh_token=${GITHUB_TOKEN:-""} + local auth_header="" + if [ ! -z "$gh_token" ]; then + auth_header="-H \"Authorization: token $gh_token\"" + fi + + curl -s -H "User-Agent: PHP-Flasher-Status-Check" $auth_header "$@" +} + +# Get GitHub stars for a repository +get_github_stars() { + local repo=$1 + local response=$(curl_cmd "https://api.github.com/repos/${ORGANIZATION}/${repo}") + local stars=$(echo "$response" | grep -o '"stargazers_count":[0-9]*' | cut -d':' -f2) + echo "${stars:-0}" +} + +# Get Packagist version +get_packagist_version() { + local package=$1 + local response=$(curl_cmd "https://repo.packagist.org/p2/php-flasher/${package}.json") + local version=$(echo "$response" | grep -o '"latest":"[^"]*"' | cut -d'"' -f4) + echo "${version:-N/A}" +} + +# Get NPM version +get_npm_version() { + local package=$1 + # Convert package name format + if [[ "$package" == "flasher" ]]; then + package="flasher" + elif [[ "$package" == *"-prime" ]]; then + # Remove -prime suffix for npm package name + package=${package%-prime} + elif [[ "$package" == *"-laravel" || "$package" == *"-symfony" ]]; then + # These packages don't have npm versions + echo "N/A" + return + fi + + local response=$(curl_cmd "https://registry.npmjs.org/@flasher/${package}/latest") + local version=$(echo "$response" | grep -o '"version":"[^"]*"' | cut -d'"' -f4) + echo "${version:-N/A}" +} + +# Display repository information +display_repo_info() { + local repo=$1 + local latest_tag=$(get_latest_tag "$repo") + local stats=($(get_repo_stats "$repo" | tr '|' ' ')) + local composer_version=$(check_composer_version) + local github_stars=$(get_github_stars "$repo") + local packagist_version=$(get_packagist_version "$repo") + local npm_version="N/A" + + # Check NPM version for main packages and those with JavaScript + if [[ "$repo" == "flasher" || "$repo" == *"-prime" || \ + "$repo" == "flasher-noty" || "$repo" == "flasher-notyf" || \ + "$repo" == "flasher-sweetalert" || "$repo" == "flasher-toastr" ]]; then + npm_version=$(get_npm_version "$repo") + fi + + echo -e "\n${BOLD}${PACKAGE} ${MAGENTA}${repo}${RESET}" + echo -e " ${BRANCH} Branch: ${stats[1]:-unknown}" + echo -e " ${TAG} Latest Tag: ${latest_tag:-none}" + echo -e " ${STAR} GitHub Stars: ${github_stars}" + echo -e " ${PACKAGIST} Packagist: v${packagist_version}" + + if [ "$npm_version" != "N/A" ]; then + echo -e " ${NPM} NPM: v${npm_version}" + fi + + echo -e " ${GITHUB} Last Commit: ${stats[0]:-unknown} (${stats[2]:-unknown})" + echo -e " ${INFO} Last Message: ${stats[3]:-unknown}" + + if [ "$composer_version" != "N/A" ]; then + echo -e " ${INFO} Composer Version: $composer_version" + fi + + local commits_since_tag=$(get_commit_count_since_tag "$repo" "$latest_tag") + if [ "$commits_since_tag" -gt 0 ]; then + warning_msg " $commits_since_tag commit(s) since last tag" + fi +} + +# Check git status +check_git_status() { + print_section "Git Status" "${GITHUB}" + + local current_branch=$(git rev-parse --abbrev-ref HEAD) + echo -e "${BOLD}Current Branch:${RESET} $current_branch" + + if [ "$current_branch" != "$MAIN_BRANCH" ]; then + warning_msg "Not on main branch ($MAIN_BRANCH)" + fi + + if [[ ! -z "$(git status --porcelain)" ]]; then + warning_msg "Working directory is not clean" + git status --short + else + success_msg "Working directory is clean" + fi + + local behind=$(git rev-list HEAD..origin/$current_branch --count 2>/dev/null || echo "0") + local ahead=$(git rev-list origin/$current_branch..HEAD --count 2>/dev/null || echo "0") + + if [ "$behind" -gt 0 ]; then + warning_msg "Branch is behind by $behind commit(s)" + fi + if [ "$ahead" -gt 0 ]; then + warning_msg "Branch is ahead by $ahead commit(s)" + fi + if [ "$behind" -eq 0 ] && [ "$ahead" -eq 0 ]; then + success_msg "Branch is up to date with origin" + fi +} + +# Check dependencies +check_dependencies() { + print_section "Dependencies" "${PACKAGE}" + + if [ -f "composer.json" ]; then + echo -e "${BOLD}Composer Dependencies:${RESET}" + composer show | grep "php-flasher/" || echo "No PHP-Flasher dependencies found" + fi + + if [ -f "package.json" ]; then + echo -e "\n${BOLD}NPM Dependencies:${RESET}" + npm list | grep "@flasher/" || echo "No Flasher dependencies found" + fi +} + +# Display modified files +display_modified_files() { + print_section "Modified Files" "šŸ“" + + local modified_files=$(git diff --name-only) + if [ ! -z "$modified_files" ]; then + echo -e "${BOLD}Modified files:${RESET}" + echo "$modified_files" + else + success_msg "No modified files" + fi +} + +# Main execution +main() { + print_header + + # Check current repository status + check_git_status + + # Check dependencies + check_dependencies + + # Display modified files + display_modified_files + + # Display repositories information + print_section "Repositories Status" "${PACKAGE}" + for repo in "${REPOSITORIES[@]}"; do + display_repo_info "$repo" + done + + # Display release readiness + print_section "Release Readiness" "${ROCKET}" + local ready=true + + if [ ! -z "$(git status --porcelain)" ]; then + warning_msg "Working directory is not clean" + ready=false + fi + + if [ "$(git rev-parse --abbrev-ref HEAD)" != "$MAIN_BRANCH" ]; then + warning_msg "Not on main branch ($MAIN_BRANCH)" + ready=false + fi + + if $ready; then + success_msg "Ready for release!" + echo -e "\n${BOLD}${GREEN}Suggested next steps:${RESET}" + echo -e "1. Run: ${ITALIC}./bin/split${RESET}" + echo -e "2. Run: ${ITALIC}./bin/release ${RESET}" + else + warning_msg "Not ready for release. Please fix the issues above." + fi +} + +# Execute main function +main diff --git a/package-lock.json b/package-lock.json index 4eb1d6f6..1ee0ae6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1939,7 +1939,7 @@ }, "node_modules/@clack/prompts/node_modules/is-unicode-supported": { "version": "1.3.0", - "extraneous": true, + "dev": true, "inBundle": true, "license": "MIT", "engines": {