Skip to content

Commit

Permalink
cumulative update (#99)
Browse files Browse the repository at this point in the history
* drop PHP versions below 8.1
* update dependencies
* merge fix for When using json() failing command has output on stdout and not stderr #90
* add symfony process 7 Adding support of symfony/process ^7.0 #94
* add docker env for develeopment
* update phpunit, fix tests to work with v11
  • Loading branch information
maschmann authored Oct 1, 2024
1 parent 30df141 commit a71d661
Show file tree
Hide file tree
Showing 16 changed files with 339 additions and 411 deletions.
22 changes: 13 additions & 9 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ jobs:

strategy:
matrix:
php:
- "8.0"
- "8.1"
- "8.2"
include:
- php-version: "8.0"
phpunit: "9.5"
- php: "8.1"
phpunit: "10"
phpunit-config: "phpunit-10.xml.dist"
- php: "8.2"
phpunit: "11"
phpunit-config: "phpunit.xml.dist"
- php: "8.3"
phpunit: "11"
phpunit-config: "phpunit.xml.dist"

steps:
Expand All @@ -28,21 +30,23 @@ jobs:
php-version: "${{ matrix.php }}"
extensions: redis, apcu, ctype, dom, iconv, gd, mbstring, fileinfo, intl, json, mysql, bcmath, zip
coverage: none # disable xdebug, pcov
ini-values: post_max_size=256M memory
#ini-values: post_max_size=256M memory
tools: cs2pr, pecl, php-cs-fixer, vimeo/psalm, phpstan, phpcs

- uses: actions/checkout@v3
- uses: actions/checkout@v4

- uses: "ramsey/composer-install@v2"
- uses: "ramsey/composer-install@v3"
with:
composer-options: "--no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist -q"

- name: PHPUnit tests
uses: php-actions/phpunit@v3
with:
version: "${{ matrix.phpunit }}"
php_version: "${{matrix.php}}"
configuration: "${{ matrix.phpunit-config }}"
memory_limit: "256M"
test_suffix: .php

- name: Run phpstan
run: phpstan analyse --error-format=checkstyle -c "phpstan.neon" | cs2pr
Expand Down
15 changes: 14 additions & 1 deletion Asm/Ansible/Command/AbstractAnsibleCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ abstract class AbstractAnsibleCommand

private array $baseOptions;

private bool $useStdoutForError;

/**
* @param ProcessBuilderInterface $processBuilder
* @param LoggerInterface|null $logger
Expand All @@ -44,6 +46,7 @@ public function __construct(ProcessBuilderInterface $processBuilder, LoggerInter
$this->options = [];
$this->parameters = [];
$this->baseOptions = [];
$this->useStdoutForError = false;
$this->setLogger($logger ?? new NullLogger());
}

Expand Down Expand Up @@ -183,7 +186,7 @@ protected function runProcess(?callable $callback): int|string

// if no callback is set, and the process is not successful, we return the output
if (false === $process->isSuccessful()) {
return $process->getErrorOutput();
return $this->useStdoutForError ? $process->getOutput() : $process->getErrorOutput();
}

// if no callback is set, and the process is successful, we return the output
Expand All @@ -210,4 +213,14 @@ protected function getProcessCommandline(Process $process): string

return sprintf('%s %s', implode(' ', $vars), $commandline);
}

/**
* in case ansible explicitly is in json mode, this will be set to be able to get error outputs
*
* @return void
*/
protected function useStdoutForError(): void
{
$this->useStdoutForError = true;
}
}
13 changes: 7 additions & 6 deletions Asm/Ansible/Command/AnsiblePlaybook.php
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ public function colors(bool $colors = true): AnsiblePlaybookInterface
public function json(): AnsiblePlaybookInterface
{
$this->processBuilder->setEnv('ANSIBLE_STDOUT_CALLBACK', 'json');
$this->useStdoutForError();

return $this;
}
Expand Down Expand Up @@ -728,12 +729,12 @@ public function hostKeyChecking(bool $enable = true): AnsiblePlaybookInterface
}

/**
* Ansible SSH pipelining option
* https://docs.ansible.com/ansible/latest/reference_appendices/config.html#ansible-pipelining
*
* @param bool $enable
* @return AnsiblePlaybookInterface
**/
* Ansible SSH pipelining option
* https://docs.ansible.com/ansible/latest/reference_appendices/config.html#ansible-pipelining
*
* @param bool $enable
* @return AnsiblePlaybookInterface
**/
public function sshPipelining(bool $enable = false): AnsiblePlaybookInterface
{
$enable ?
Expand Down
24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM php:8.3-cli

WORKDIR /app

ENV ANSIBLE_VERSION 2.9.17

# composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php \
&& php -r "unlink('composer-setup.php');" \
&& mv composer.phar /usr/bin/composer \
&& chmod +x /usr/bin/composer

# python, pipx & ansible
RUN apt-get update \
&& apt-get install -y gcc python3 git zip 7zip unzip pipx \
&& apt-get clean all; \
pipx install --upgrade pip; \
pipx install "ansible==${ANSIBLE_VERSION}"; \
pipx install ansible;

# keep container running
CMD [ "bash", "-c", "echo 'running'; tail -f /dev/null" ]
66 changes: 66 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Executables (local)
DOCKER_COMP = docker compose

# Docker containers
PHP_CONT = $(DOCKER_COMP) exec php-ansible

# Executables
PHP = $(PHP_CONT) php
COMPOSER = $(PHP_CONT) composer

# Misc
.DEFAULT_GOAL = help

## —— php-ansible Makefile 🎵 ——————————————————————————————————
help: ## Outputs this help screen
@grep -E '(^[a-zA-Z0-9\./_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'

## —— Docker 🐳 ————————————————————————————————————————————————————————————————
build: ## Builds the Docker images
@$(DOCKER_COMP) build --pull --no-cache

up: ## Start the docker hub in detached mode (no logs)
@$(DOCKER_COMP) up --detach

start: build up ## Build and start the containers

down: ## Stop the docker hub
@$(DOCKER_COMP) down --remove-orphans

logs: ## Show live logs
@$(DOCKER_COMP) logs --tail=0 --follow

sh: ## Connect to the php-fpm container
@$(PHP_CONT) sh

bash: ## Connect to the php-fpm container via bash so up and down arrows go to previous commands
@$(PHP_CONT) bash

test: ## Start tests with phpunit, pass the parameter "c=" to add options to phpunit, example: make test c="--group e2e --stop-on-failure"
@$(eval c ?=)
@$(PHP_CONT) vendor/bin/phpunit -c phpunit.xml.dist $(c)

analyze: ## Start analysis with phpstan, pass the parameter "c=" to add options to phpstan. Default config ist always used, example: make analyze c="--group e2e"
@$(eval c ?=)
@$(PHP_CONT) vendor/bin/phpstan --configuration=phpstan.neon $(c)

codestyle: ## Start codestyle analysis with phpcs, pass the parameter "c=" to add options to phpcs. Default config ist always used. Example: make codestyle c="--parallel=2"
@$(eval c ?=)
@$(PHP_CONT) vendor/bin/phpcs --standard=phpcs.xml.dist $(c)

codestyle-fix: ## Start codestyle analysis with phpcbf, pass the parameter "c=" to add options to phpcbf. Default config ist always used. Example: make codestyle c="--parallel=2"
@$(eval c ?=)
@$(PHP_CONT) vendor/bin/phpcbf --standard=phpcs.xml.dist $(c)

psalm: ## Start code analysis with psalm, pass the parameter "c=" to add options to psalm. Default config ist always used. Example: make codestyle c="--level=2"
@$(eval c ?=)
@$(DOCKER_COMP) exec -e APP_ENV=dev php vendor/bin/psalm --config=psalm.xml $(c)

## —— Composer 🧙 ——————————————————————————————————————————————————————————————
composer: ## Run composer, pass the parameter "c=" to run a given command, example: make composer c='req phpstan/phpstan'
@$(eval c ?=)
@$(COMPOSER) $(c)

vendor: ## Install vendors according to the current composer.lock file
vendor: c=install --prefer-dist --no-dev --no-progress --no-scripts --no-interaction
vendor: composer
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,12 @@ $ansible
```

## Development

You can use the provided docker image with ```make build``` which uses a default php-cli docker image and ansible 2.x. See the ```Dockerfile``` for more info.
Start the container with ```make up```.
Composer install: ```make vendor```
You can run code or the tests within the container: ```make test c="--testdox"```

## Thank you for your contributions!

Expand All @@ -178,7 +183,6 @@ The Next steps for implementation are:
- improve type handling and structure, due to overall complexity of the playbook at the moment
- scalar typehints all over the place
- provide docker support for development
- move to php8.0 exclusively for the next major release
- wrapping the library into a bundle -> maybe
- provide commandline-capabilities -> maybe

Expand Down
58 changes: 11 additions & 47 deletions Tests/Asm/Ansible/AnsibleTest.php
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
<?php
/*
* This file is part of the php-ansible package.
*
* (c) Marc Aschmann <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Asm\Ansible;

use Asm\Ansible\Exception\CommandException;
use Asm\Ansible\Testing\AnsibleTestCase;
use org\bovigo\vfs\vfsStream;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversFunction;

#[CoversClass(\Asm\Ansible\Ansible::class)]
#[CoversFunction('playbook')]
#[CoversFunction('createProcess')]
#[CoversFunction('checkCommand')]
#[CoversFunction('checkDir')]
#[CoversFunction('__construct')]
class AnsibleTest extends AnsibleTestCase
{
/**
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/

public function testInstance()
{
$ansible = new Ansible(
Expand All @@ -31,11 +29,6 @@ public function testInstance()
$this->assertInstanceOf('\Asm\Ansible\Ansible', $ansible, 'Instantiation with given paths');
}

/**
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testAnsibleProjectPathNotFoundException()
{
$this->expectException(CommandException::class);
Expand All @@ -46,11 +39,6 @@ public function testAnsibleProjectPathNotFoundException()
);
}

/**
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testAnsibleCommandNotFoundException()
{
$this->expectException(CommandException::class);
Expand All @@ -61,11 +49,6 @@ public function testAnsibleCommandNotFoundException()
);
}

/**
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testAnsibleNoCommandGivenException()
{
// TODO: Not sure why the following command should give an error.
Expand All @@ -75,11 +58,6 @@ public function testAnsibleNoCommandGivenException()
// );
}

/**
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testAnsibleCommandNotExecutableException()
{
$this->expectException(CommandException::class);
Expand All @@ -94,13 +72,6 @@ public function testAnsibleCommandNotExecutableException()
);
}

/**
* @covers \Asm\Ansible\Ansible::playbook
* @covers \Asm\Ansible\Ansible::createProcess
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testPlaybookCommandInstance()
{
$ansible = new Ansible(
Expand All @@ -114,13 +85,6 @@ public function testPlaybookCommandInstance()
$this->assertInstanceOf('\Asm\Ansible\Command\AnsiblePlaybook', $playbook);
}

/**
* @covers \Asm\Ansible\Ansible::galaxy
* @covers \Asm\Ansible\Ansible::createProcess
* @covers \Asm\Ansible\Ansible::checkCommand
* @covers \Asm\Ansible\Ansible::checkDir
* @covers \Asm\Ansible\Ansible::__construct
*/
public function testGalaxyCommandInstance()
{
$ansible = new Ansible(
Expand Down
7 changes: 2 additions & 5 deletions Tests/Asm/Ansible/Command/AnsibleGalaxyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,15 @@ public function testCreateInstance(): AnsibleGalaxyInterface
return $ansibleGalaxy;
}

/**
* @depends testCreateInstance
* @param AnsibleGalaxyInterface $command
*/
public function testExecute(AnsibleGalaxyInterface $command): void
public function testExecute(): void
{
// Skipped on Windows
if (Env::isWindows()) {
$this->assertTrue(true);
return;
}

$command = $this->testCreateInstance();
$command->execute();

// if command executes without exception
Expand Down
Loading

0 comments on commit a71d661

Please sign in to comment.