Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@
/dock export-ignore
/test.sh export-ignore
/art/ export-ignore
`
156 changes: 145 additions & 11 deletions .github/workflows/docblock_update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,164 @@ jobs:
- name: Checkout code
uses: actions/checkout@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }}
ref: ${{ github.head_ref || github.ref }}
fetch-depth: 0

- name: Update docblocks
run: |
set -e
SOURCE_URL=$(jq -r '.support.source' composer.json)
if [ ! -d ./src ]; then
echo "Source directory ./src does not exist!"
exit 1
fi
docker run --rm -v "$PWD/src:/app/run" davidsmith3/docblock-annotator-cli \
docblock-annotator-cli:update-directory /app/run "@link $SOURCE_URL"
set -euo pipefail

# Constants
readonly COMPOSER_JSON="composer.json"
readonly DOCBLOCK_DOCKER_IMAGE="davidsmith3/docblock-annotator-cli"
readonly DOCBLOCK_COMMAND="docblock-annotator-cli:update-file"

# Execute docblock annotator via Docker for a specific file
execute_docblock_annotator() {
local file_path="$1"
shift

docker run \
--rm \
--volume "$(pwd):/app/run" \
"${DOCBLOCK_DOCKER_IMAGE}" \
"${DOCBLOCK_COMMAND}" \
"/app/run/${file_path}" \
"$@"
}

# Validate required dependencies are available
validate_dependencies() {
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed." >&2
return 1
fi

if [[ ! -f "${COMPOSER_JSON}" ]]; then
echo "Error: ${COMPOSER_JSON} not found in current directory." >&2
return 1
fi
}

# Extract the main PHP class file path from composer.json PSR-4 autoload configuration
get_main_class_file() {
local namespace directory class_name php_file

namespace=$(jq -r '.autoload."psr-4" | keys[0] // empty' "${COMPOSER_JSON}")
directory=$(jq -r --arg ns "$namespace" '.autoload."psr-4"[$ns] // empty' "${COMPOSER_JSON}")

if [[ -z "$namespace" || -z "$directory" ]]; then
echo "Error: Could not extract PSR-4 namespace or directory from ${COMPOSER_JSON}." >&2
return 1
fi

# Remove trailing backslash from namespace
namespace="${namespace%\\}"

# Extract class name from namespace (last segment)
class_name=$(echo "$namespace" | awk -F'\\\\' '{print $NF}')

# Construct PHP file path
php_file="${directory}${class_name}.php"

# Convert backslashes to forward slashes for file path
php_file=$(echo "$php_file" | sed 's/\\/\//g')

if [[ ! -f "$php_file" ]]; then
echo "Error: Main class file '$php_file' not found." >&2
return 1
fi

echo "$php_file"
}

# Extract package description from composer.json
get_package_description() {
local description
description=$(jq -r '.description // empty' "${COMPOSER_JSON}")

if [[ -z "$description" ]]; then
echo "Error: Could not extract package description from ${COMPOSER_JSON}." >&2
return 1
fi

echo "$description"
}

# Extract package homepage from composer.json
get_package_homepage() {
local homepage
homepage=$(jq -r '.homepage // empty' "${COMPOSER_JSON}")

if [[ -z "$homepage" ]]; then
echo "Error: Could not extract package homepage from ${COMPOSER_JSON}." >&2
return 1
fi

echo "$homepage"
}

# Update docblock with package description
update_docblock_with_description() {
local php_file description

php_file=$(get_main_class_file) || return 1
description=$(get_package_description) || return 1

execute_docblock_annotator "$php_file" "$description" "--statements=class"
}

# Update docblock with homepage link
update_docblock_with_link() {
local php_file homepage

php_file=$(get_main_class_file) || return 1
homepage=$(get_package_homepage) || return 1

execute_docblock_annotator "$php_file" "@link $homepage"
}

# Main function to update all docblocks
update_package_docblocks() {
validate_dependencies || return 1

echo "Updating docblocks with package description..."
update_docblock_with_description || return 1

echo "Updating docblocks with homepage link..."
update_docblock_with_link || return 1

echo "Docblock updates completed successfully."
}

# Execute the main function
update_package_docblocks

- name: Commit and push changes (if any)
run: |
set -e
set -euo pipefail

# Configure git user for commits
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"

# Stage all changes
git add -A

# Check if there are any changes to commit
if ! git diff --cached --quiet; then
git commit -m "Update docblocks with @link annotations" --no-verify
echo "Changes detected, committing docblock updates..."

# Commit without skip-ci to allow other workflows to run
git commit -m "Update docblocks with @link annotations" \
--no-verify

# Push changes - using PAT_TOKEN if available to trigger workflows properly
git push

echo "Docblock updates committed and pushed successfully."
echo "Other workflows will run on the new commit."
else
echo "No changes to commit."
fi
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:

strategy:
matrix:
php-version: ["8.4", "8.3", "8.2", "8.1"]
php-version: ["8.5", "8.4", "8.3", "8.2", "8.1"]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- name: Create .env
run: touch .env
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Documentation Publishing](#documentation-publishing)
- [Automatic Documentation Publishing](#automatic-documentation-publishing)
- [Local Development](./LOCAL_DEVELOPMENT.md)
- [Contributing](#contributing)

Expand Down Expand Up @@ -57,6 +59,39 @@ echo $SocketClient->remoteSocketName(); // 34.223.124.45:443
$SocketClient->close();
```

## Documentation Publishing

You can publish this README to your local documentation directory.

This can be useful for providing documentation for AI agents.

This can be done using the included script:

```bash
# Publish to default location (./docs/zero-to-prod/stream-socket)
vendor/bin/zero-to-prod-stream-socket

# Publish to custom directory
vendor/bin/zero-to-prod-stream-socket /path/to/your/docs
```

### Automatic Documentation Publishing

You can automatically publish documentation by adding the following to your `composer.json`:

```json
{
"scripts": {
"post-install-cmd": [
"zero-to-prod-stream-socket"
],
"post-update-cmd": [
"zero-to-prod-stream-socket"
]
}
}
```

## Contributing

Contributions, issues, and feature requests are welcome!
Expand Down
32 changes: 32 additions & 0 deletions bin/zero-to-prod-stream-socket
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env php
<?php

/**
* Zero-to-Prod Stream Socket Documentation Publisher
*
* Publishes the README.md file to the user's documentation directory.
*/

require getcwd().'/vendor/autoload.php';

use Zerotoprod\PackageHelper\PackageHelper;

$target_path = getcwd().'/docs/zero-to-prod/stream-socket/';
if (isset($argv[1])) {
$target_path = rtrim($argv[1], '/').'/';
}

$source_file = __DIR__.'/../README.md';

if (!file_exists($source_file)) {
fwrite(STDERR, "Error: Not found $source_file\n");
exit(1);
}

try {
PackageHelper::copy($source_file, $target_path);
exit(0);
} catch (RuntimeException $e) {
fwrite(STDERR, "Error: ".$e->getMessage()."\n");
exit(1);
}
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,8 @@
},
"suggest": {
"zero-to-prod/stream-context": "A wrapper for stream_context_create()."
}
},
"bin": [
"bin/zero-to-prod-stream-socket"
]
}
27 changes: 27 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
services:
php8.5:
volumes:
- ./:/app:delegated
- ./.vendor/php8.5:/app/vendor
build:
context: ./docker/8.5
target: base

debug8.5:
extends:
service: php8.5
volumes:
- ./:/app:delegated
- ./docker/8.5:/usr/local/etc/php
- ./.vendor/php8.5:/app/vendor
build:
target: debug

composer8.5:
extends:
service: php8.5
volumes:
- ./:/app:delegated
- ./.vendor/php8.5:/app/vendor
build:
target: composer

php8.1:
volumes:
- ./:/app:delegated
Expand Down
1 change: 1 addition & 0 deletions docker/8.5/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.phpunit.result.cache
33 changes: 33 additions & 0 deletions docker/8.5/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM php:8.5-rc-alpine AS builder

RUN apk add --no-cache \
git \
unzip \
$PHPIZE_DEPS

RUN git config --global --add safe.directory /app

WORKDIR /app

FROM builder AS composer

RUN curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/local/bin \
--filename=composer

FROM builder AS debug

RUN apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
linux-headers \
&& pecl channel-update pecl.php.net \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug \
&& apk del .build-deps \
&& rm -rf /tmp/* /var/cache/apk/*

FROM php:8.5-rc-alpine AS base

WORKDIR /app

CMD ["bash"]
5 changes: 5 additions & 0 deletions docker/8.5/php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
zend_extension = xdebug.so
xdebug.mode = debug
xdebug.start_with_request = yes
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
2 changes: 1 addition & 1 deletion test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -e

PHP_VERSIONS=("8.4" "8.3" "8.2" "8.1")
PHP_VERSIONS=("8.5" "8.4" "8.3" "8.2" "8.1")

for PHP_VERSION in "${PHP_VERSIONS[@]}"; do

Expand Down