You've already forked gitea-composer-upload-action
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47dac3fa50 | ||
|
|
06bdf2c9c2 | ||
|
|
b9541200da | ||
|
|
5eb9495529 | ||
|
|
53455912a8 | ||
|
|
705a50d681 | ||
|
|
7744d22039 | ||
|
|
1fbc211eed | ||
|
|
431cd5ca43 | ||
|
|
af9260a35c |
@@ -0,0 +1,4 @@
|
||||
.idea
|
||||
.github
|
||||
var
|
||||
vendor
|
||||
|
||||
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@@ -0,0 +1,20 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
7
.env.dist
Normal file
7
.env.dist
Normal file
@@ -0,0 +1,7 @@
|
||||
PHP_VERSION="8.3"
|
||||
|
||||
GITEA_INSTANCE_BASE_URL="https://gitea.example.com"
|
||||
GITEA_ACCESS_TOKEN="access_token"
|
||||
GITEA_OWNER="owner"
|
||||
GITEA_REPOSITORY="repository"
|
||||
GITEA_PACKAGE_REGISTRY="composer"
|
||||
@@ -1,5 +1,7 @@
|
||||
PHP_VERSION="8.3"
|
||||
|
||||
GITEA_INSTANCE_BASE_URL="https://gitea.example.com"
|
||||
GITEA_ACCESS_TOKEN="access_token"
|
||||
GITEA_OWNER="owner"
|
||||
GITEA_REPOSITORY="repository"
|
||||
GITEA_PACKAGE_REGISTRY="composer"
|
||||
GITEA_PACKAGE_REGISTRY="composer"
|
||||
|
||||
26
.gitattributes
vendored
Normal file
26
.gitattributes
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
* text=auto
|
||||
|
||||
AUTHORS text
|
||||
CHANGELOG text
|
||||
CHANGES text
|
||||
CONTRIBUTING text
|
||||
COPYING text
|
||||
LICENSE text
|
||||
NEWS text
|
||||
.editorconfig text
|
||||
.gitattributes text
|
||||
.gitconfig text
|
||||
|
||||
.env text
|
||||
.env.example text
|
||||
.env.ci text
|
||||
.gitignore text
|
||||
.dockerignore text
|
||||
Dockerfile text
|
||||
Makefile text
|
||||
composer.json text eol=lf
|
||||
*.md text diff=markdown
|
||||
*.php text diff=php
|
||||
*.sh text eol=lf
|
||||
*.yml text
|
||||
*.json text
|
||||
197
.github/workflows/tests.yml
vendored
Normal file
197
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
name: tests
|
||||
|
||||
on:
|
||||
pull_request: ~
|
||||
push:
|
||||
branches: ['*.*.*']
|
||||
|
||||
env:
|
||||
BRANCH: ${{ github.head_ref || github.ref_name }}
|
||||
|
||||
jobs:
|
||||
docker-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- run: cp .env.dist .env
|
||||
- uses: falti/dotenv-action@v1
|
||||
id: dotenv
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
PHP_VERSION=${{ steps.dotenv.outputs.PHP_VERSION }}
|
||||
push: false
|
||||
composer-validate:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- run: composer validate
|
||||
composer-normalize:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer normalize
|
||||
composer-require-checker:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer require-checker
|
||||
composer-unused:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer unused
|
||||
linter:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2, cs2pr
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer php-cs-fixer -- --dry-run --diff --format=checkstyle --ansi | cs2pr
|
||||
refactoring:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer rector -- --dry-run
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer psalm -- --php-version=${{ matrix.php }} --stats --output-format=github --shepherd
|
||||
unit-tests:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: pcov
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
# - run: composer test -- --colors=always --order-by=random --coverage-clover coverage.xml
|
||||
- run: composer phpunit
|
||||
mutation-tests:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
php:
|
||||
- 8.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{env.BRANCH}}
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v2
|
||||
coverage: pcov
|
||||
- uses: ramsey/composer-install@v3
|
||||
with:
|
||||
composer-options: --optimize-autoloader
|
||||
- run: composer infection
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
.idea
|
||||
/.env
|
||||
.env
|
||||
vendor
|
||||
|
||||
27
.php-cs-fixer.dist.php
Normal file
27
.php-cs-fixer.dist.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use PhpCsFixer\Config;
|
||||
use PhpCsFixer\Finder;
|
||||
use PHPyh\CodingStandard\PhpCsFixerCodingStandard;
|
||||
|
||||
$finder = Finder::create()
|
||||
->in([
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->append([
|
||||
__FILE__,
|
||||
])
|
||||
->notPath([
|
||||
'benchmark.php',
|
||||
]);
|
||||
|
||||
$config = (new Config())
|
||||
->setFinder($finder)
|
||||
->setCacheFile(__DIR__ . '/var/.php-cs-fixer.cache');
|
||||
|
||||
(new PhpCsFixerCodingStandard())->applyTo($config);
|
||||
|
||||
return $config;
|
||||
33
Dockerfile
33
Dockerfile
@@ -1,9 +1,30 @@
|
||||
FROM cybercinch/base-alpine-bash:latest
|
||||
ARG PHP_VERSION=8.3
|
||||
|
||||
COPY scripts/docker-entrypoint.sh /entrypoint.sh
|
||||
RUN chmod a+x /entrypoint.sh
|
||||
FROM rosven9856/php:$PHP_VERSION
|
||||
|
||||
ENV upload_file="build/Package.zip"
|
||||
ENV overwrite_files="false"
|
||||
RUN apk add --update --no-cache --virtual .build-deps ${PHPIZE_DEPS} \
|
||||
&& pecl install pcov \
|
||||
&& docker-php-ext-enable pcov \
|
||||
&& apk del .build-deps
|
||||
|
||||
CMD ["/entrypoint.sh"]
|
||||
RUN addgroup -g 1000 --system php
|
||||
RUN adduser -G php --system -D -s /bin/sh -u 1000 php
|
||||
|
||||
RUN chown php:php /home/php
|
||||
RUN chown php:php /usr/local/bin/composer
|
||||
|
||||
RUN mkdir /usr/bin/app
|
||||
RUN chown -R php:php /usr/bin/app
|
||||
|
||||
COPY . /usr/bin/app
|
||||
WORKDIR /usr/bin/app
|
||||
|
||||
ENV GITHUB_WORKSPACE=/usr/bin/app
|
||||
|
||||
RUN composer install
|
||||
|
||||
VOLUME ["/usr/bin/app"]
|
||||
|
||||
USER php
|
||||
|
||||
CMD ["php", "-f", "/usr/bin/app/app.php"]
|
||||
|
||||
38
README.md
38
README.md
@@ -2,7 +2,7 @@
|
||||
<img width="560" height="260" src="docs/image/github_gitea_actions.jpg" alt="github gitea actions">
|
||||
</p>
|
||||
|
||||
# Add/Update a Composer package in Gitea
|
||||
# Updating a package in the Gitea system using GitHub Actions
|
||||
|
||||
[](https://github.com/rosven9856/gitea-package-action/blob/master/LICENSE)
|
||||
|
||||
@@ -13,10 +13,34 @@ This action will update the package version in the Gitea system using the API an
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: https://hub.cybercinch.nz/gitea-composer-upload@main
|
||||
- uses: rosven9856/gitea-package-action@0.1.0
|
||||
with:
|
||||
base_url: "https://gitea_instance_url"
|
||||
access_token: "${{ secrets._G_TOKEN }}"
|
||||
username: "${{ secrets._G_USERNAME }}"
|
||||
owner: "owner"
|
||||
package_version: "${{ env.GITHUB_REF_NAME }}"
|
||||
gitea_instance_base_url: "https://gitea_instance_url"
|
||||
gitea_access_token: "${{ secrets._GITEA_ACCESS_TOKEN }}"
|
||||
gitea_owner: "owner"
|
||||
gitea_repository: "repository"
|
||||
gitea_package_registry: "composer"
|
||||
```
|
||||
|
||||
|
||||
## Developing
|
||||
|
||||
build
|
||||
```shell
|
||||
docker build . --build-arg=PHP_VERSION=8.3 -t=gitea-package-action
|
||||
```
|
||||
|
||||
initialization
|
||||
```shell
|
||||
docker run --rm -v .:/usr/bin/app gitea-package-action composer install
|
||||
```
|
||||
|
||||
running
|
||||
```shell
|
||||
docker run --rm -v .:/usr/bin/app gitea-package-action php app.php
|
||||
```
|
||||
|
||||
testing
|
||||
```shell
|
||||
docker run --rm -v .:/usr/bin/app gitea-package-action composer tests
|
||||
```
|
||||
|
||||
12
action.Dockerfile
Normal file
12
action.Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
||||
ARG PHP_VERSION=8.3
|
||||
|
||||
FROM rosven9856/php:$PHP_VERSION
|
||||
|
||||
COPY . /usr/bin/app
|
||||
WORKDIR /usr/bin/app
|
||||
|
||||
RUN composer install --optimize-autoloader
|
||||
|
||||
VOLUME ["/usr/bin/app"]
|
||||
|
||||
ENTRYPOINT ["php", "-f", "/usr/bin/app/app.php"]
|
||||
51
action.yml
51
action.yml
@@ -1,39 +1,30 @@
|
||||
name: "Gitea Composer upload package"
|
||||
description: "Updating a composer package in the Gitea system using GitHub Actions"
|
||||
name: "Gitea updating package"
|
||||
description: "Updating a package in the Gitea system using GitHub Actions"
|
||||
inputs:
|
||||
baseurl:
|
||||
description: "Base URL for Gitea Instance"
|
||||
gitea_instance_base_url:
|
||||
description: "gitea instance base url"
|
||||
required: true
|
||||
username:
|
||||
description: "Username"
|
||||
gitea_access_token:
|
||||
description: "gitea access token"
|
||||
required: true
|
||||
access_token:
|
||||
description: "Access Token"
|
||||
gitea_owner:
|
||||
description: "gitea owner"
|
||||
required: true
|
||||
owner:
|
||||
description: "Package owner"
|
||||
required: false
|
||||
version:
|
||||
description: "Version of package"
|
||||
gitea_repository:
|
||||
description: "gitea repository"
|
||||
required: true
|
||||
gitea_package_registry:
|
||||
description: "gitea package registry"
|
||||
required: true
|
||||
overwrite_files:
|
||||
description: "Overwrite package if already exists"
|
||||
required: false
|
||||
default: "false"
|
||||
upload_file:
|
||||
description: "The file path to upload"
|
||||
required: false
|
||||
default: "build/Package.zip"
|
||||
runs:
|
||||
using: "docker"
|
||||
image: "Dockerfile"
|
||||
env:
|
||||
baseurl: ${{ inputs.baseurl }}
|
||||
username: ${{ inputs.username }}
|
||||
access_token: ${{ inputs.access_token }}
|
||||
version: ${{ inputs.version }}
|
||||
overwrite_files: ${{ inputs.overwrite_files }}
|
||||
|
||||
image: "action.Dockerfile"
|
||||
args:
|
||||
- ${{ inputs.gitea_instance_base_url }}
|
||||
- ${{ inputs.gitea_access_token }}
|
||||
- ${{ inputs.gitea_owner }}
|
||||
- ${{ inputs.gitea_repository }}
|
||||
- ${{ inputs.gitea_package_registry }}
|
||||
branding:
|
||||
icon: 'package'
|
||||
color: 'green'
|
||||
color: 'green'
|
||||
|
||||
252
app.php
Normal file
252
app.php
Normal file
@@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Action;
|
||||
use App\Configuration\Configuration;
|
||||
use App\Casting\MapperType;
|
||||
|
||||
\define('RED', "\033[0;31m");
|
||||
\define('GREEN', "\033[1;32m");
|
||||
\define('YELLOW', "\033[1;33m");
|
||||
\define('LITE_CYAN', "\e[96m");
|
||||
\define('NC', "\033[0m");
|
||||
|
||||
try {
|
||||
|
||||
$configuration = (new Configuration())
|
||||
->set('base_url', \getenv('gitea_instance_base_url'))
|
||||
->set('access_token', \getenv('gitea_access_token'))
|
||||
->set('owner', \getenv('gitea_owner'))
|
||||
->set('owner', \getenv('gitea_owner'))
|
||||
->set('repository', \getenv('gitea_repository'))
|
||||
->set('package_registry', \getenv('gitea_package_registry'))
|
||||
;
|
||||
|
||||
(new Action($configuration))->run();
|
||||
|
||||
} catch (Exception) {
|
||||
// echo 'Error: ' . $e->getMessage() . "\n" . 'Trace: ' . $e->getTraceAsString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sendRequest ($method = 'GET', $endpoint = '', $data = []): array {
|
||||
|
||||
if (!\extension_loaded('curl')) {
|
||||
throw new \Exception('CURL extension is not loaded');
|
||||
}
|
||||
|
||||
$curl = \curl_init();
|
||||
|
||||
if(!$curl) {
|
||||
throw new \Exception('CURL extension is not loaded');
|
||||
}
|
||||
|
||||
$payload = '';
|
||||
|
||||
if (isset($data['request']) && \is_array($data['request']) && \count($data['request']) > 0) {
|
||||
$payload = \json_encode($data['request']);
|
||||
}
|
||||
|
||||
$fh = null;
|
||||
$fileSize = 0;
|
||||
|
||||
if (isset($data['file']) && !empty($data['file']) && \file_exists($data['file'])) {
|
||||
$fh = \fopen($data['file'], 'r');
|
||||
$fileSize = \filesize($data['file']);
|
||||
}
|
||||
|
||||
if (isset($data['user']) && !empty($data['user'])) {
|
||||
\curl_setopt($curl, CURLOPT_USERPWD, $data['user'] . ':' . \getenv('gitea_access_token'));
|
||||
} else {
|
||||
$endpoint .= '?access_token=' . \getenv('gitea_access_token');
|
||||
}
|
||||
|
||||
\curl_setopt($curl, CURLOPT_URL, \getenv('gitea_instance_base_url') . $endpoint /* . '?access_token=' . \getenv('gitea_access_token')*/);
|
||||
\curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
\curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
|
||||
\curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
\curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
|
||||
if ($method === 'POST' || $method === 'PUT') {
|
||||
if (!empty($payload)) {
|
||||
\curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
|
||||
\curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($method === 'PUT') {
|
||||
\curl_setopt($curl, CURLOPT_PUT, true);
|
||||
}
|
||||
|
||||
if ($fh) {
|
||||
\curl_setopt($curl, CURLOPT_INFILE, $fh);
|
||||
\curl_setopt($curl, CURLOPT_INFILESIZE, $fileSize);
|
||||
}
|
||||
|
||||
\curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20);
|
||||
\curl_setopt($curl, CURLOPT_TIMEOUT, 20);
|
||||
|
||||
$response = \curl_exec($curl);
|
||||
|
||||
if(\curl_errno($curl) > 0) {
|
||||
throw new \Exception('Curl error: #' . \curl_errno($curl) . ' - ' . \curl_error($curl));
|
||||
}
|
||||
|
||||
$header = \substr($response, 0, \curl_getinfo($curl, CURLINFO_HEADER_SIZE));
|
||||
$body = \substr($response, \curl_getinfo($curl, CURLINFO_HEADER_SIZE));
|
||||
$httpCode = (int) \curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$contentType = \curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
|
||||
|
||||
$headers = \explode("\r\n", $header);
|
||||
|
||||
\curl_close($curl);
|
||||
|
||||
if (isset($data['file']) && !empty($data['file']) && \file_exists($data['file'])) {
|
||||
\fclose($fh);
|
||||
}
|
||||
|
||||
return [
|
||||
'http_code' => $httpCode,
|
||||
'content_type' => $contentType,
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
}
|
||||
|
||||
function responseEncode (array $response): mixed {
|
||||
|
||||
$data = [];
|
||||
|
||||
if ($response['content_type'] !== 'application/json;charset=utf-8') {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$data = \json_decode($response['body'], true);
|
||||
|
||||
if (\json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new \Exception('Invalid response json: ' . json_last_error_msg());
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function showTerminalMessage (string $message = '', string $color = ''): void
|
||||
{
|
||||
echo $color . $message . NC . "\r\n";
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (empty(\getenv('gitea_instance_base_url'))) {
|
||||
throw new \Exception('gitea_instance_base_url empty');
|
||||
}
|
||||
|
||||
if (empty(\getenv('gitea_access_token'))) {
|
||||
throw new \Exception('gitea_access_token empty');
|
||||
}
|
||||
|
||||
if (empty(\getenv('gitea_owner'))) {
|
||||
throw new \Exception('gitea_owner empty');
|
||||
}
|
||||
|
||||
if (empty(\getenv('gitea_repository'))) {
|
||||
throw new \Exception('gitea_repository empty');
|
||||
}
|
||||
|
||||
if (empty(\getenv('gitea_package_registry'))) {
|
||||
throw new \Exception('gitea_package_registry empty');
|
||||
}
|
||||
|
||||
if (!\in_array(\getenv('gitea_package_registry'), ['composer'])) {
|
||||
throw new \Exception('Package registry {' . \getenv('gitea_package_registry') . '} is not supported');
|
||||
}
|
||||
|
||||
$response = sendRequest('GET', '/api/v1/user');
|
||||
|
||||
if ($response['http_code'] !== 200) {
|
||||
throw new \Exception('Failed to get user information. Access denied. Response http code: ' . $response['http_code']);
|
||||
}
|
||||
|
||||
$data = responseEncode($response);
|
||||
|
||||
if ($response['http_code'] !== 200) {
|
||||
throw new \Exception('Failed to get user information. Response http code: ' . $response['http_code'] . ', Message: ' . $data['message']);
|
||||
}
|
||||
|
||||
$user = $data;
|
||||
$login = $user['login'];
|
||||
showTerminalMessage('User data: OK', GREEN);
|
||||
|
||||
|
||||
|
||||
$response = sendRequest('GET', '/api/v1/repos/' . \getenv('gitea_owner') . '/' . \getenv('gitea_repository') . '/releases', [
|
||||
'user' => $login,
|
||||
]);
|
||||
|
||||
if ($response['http_code'] !== 200) {
|
||||
throw new \Exception('Failed to get repository releases information. Access denied. Response http code: ' . $response['http_code']);
|
||||
}
|
||||
|
||||
$data = responseEncode($response);
|
||||
|
||||
if ($response['http_code'] !== 200) {
|
||||
throw new \Exception('Failed to get repository releases information. Response http code: ' . $response['http_code'] . ', Message: ' . $data['message']);
|
||||
}
|
||||
|
||||
if (!isset($data[0]) || !\is_array($data[0])) {
|
||||
throw new \Exception('Unexpected release data structure');
|
||||
}
|
||||
|
||||
$lastRelease = $data[0];
|
||||
$tag = $lastRelease['tag_name'];
|
||||
showTerminalMessage('Last release data: OK', GREEN);
|
||||
|
||||
|
||||
$response = sendRequest('GET', '/api/v1/repos/' . \getenv('gitea_owner') . '/' . \getenv('gitea_repository') . '/archive/' . $tag . '.zip', [
|
||||
'user' => $login,
|
||||
]);
|
||||
$zipContent = $response['body'];
|
||||
|
||||
if ($response['http_code'] !== 200) {
|
||||
throw new \Exception('Failed receiving zip archive. Response http code: ' . $response['http_code']);
|
||||
}
|
||||
|
||||
if (empty($response['body'])) {
|
||||
throw new \Exception('Failed receiving zip archive. Empty file');
|
||||
}
|
||||
|
||||
\file_put_contents(__DIR__ . '/package.zip', $zipContent);
|
||||
showTerminalMessage('Download zip archive: OK', GREEN);
|
||||
|
||||
|
||||
|
||||
$response = sendRequest('PUT', '/api/packages/' . \getenv('gitea_owner') . '/composer?version=' . $tag, [
|
||||
'user' => $login,
|
||||
'file' => __DIR__ . '/package.zip',
|
||||
]);
|
||||
|
||||
\unlink(__DIR__ . '/package.zip');
|
||||
|
||||
if ($response['http_code'] !== 201) {
|
||||
$data = responseEncode($response);
|
||||
|
||||
throw new \Exception('Failed update package. Response http code: ' . $response['http_code'] . ', Message: ' . $data['errors'][0]['message']);
|
||||
}
|
||||
|
||||
showTerminalMessage('Update package: OK', GREEN);
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
showTerminalMessage("\r\n");
|
||||
showTerminalMessage( 'FAILED!', RED);
|
||||
showTerminalMessage( "Error: " . $e->getMessage(), RED);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
showTerminalMessage("\r\n");
|
||||
showTerminalMessage('SUCCESS!', GREEN);
|
||||
17
compose.yml
17
compose.yml
@@ -1,17 +0,0 @@
|
||||
services:
|
||||
composer-uploader:
|
||||
container_name: compose-upload-gitea
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
baseurl: ${base_url}
|
||||
access_token: ${access_token}
|
||||
username: ${username}
|
||||
owner: ${owner}
|
||||
version: ${version}
|
||||
repo_name: ${repo_name}
|
||||
overwrite_files: true
|
||||
working_dir: /
|
||||
volumes:
|
||||
- ./build:/build
|
||||
16
composer-require-checker.json
Normal file
16
composer-require-checker.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"symbol-whitelist" : [],
|
||||
"php-core-extensions" : [
|
||||
"Core",
|
||||
"date",
|
||||
"json",
|
||||
"hash",
|
||||
"pcre",
|
||||
"Phar",
|
||||
"Reflection",
|
||||
"SPL",
|
||||
"random",
|
||||
"standard"
|
||||
],
|
||||
"scan-files" : []
|
||||
}
|
||||
68
composer.json
Normal file
68
composer.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "rosven9856/gitea-package-action",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "rosven9856",
|
||||
"email": "rosven9856@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.3",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ergebnis/composer-normalize": "^2.42",
|
||||
"friendsofphp/php-cs-fixer": "^3.57",
|
||||
"icanhazstring/composer-unused": "^0.8.11",
|
||||
"infection/infection": "^0.27.11",
|
||||
"maglnet/composer-require-checker": "^4.11",
|
||||
"phpunit/phpunit": "^10.4.2",
|
||||
"phpyh/coding-standard": "^2.6",
|
||||
"psalm/plugin-phpunit": "^0.18.4",
|
||||
"rector/rector": "^1.1",
|
||||
"symfony/var-dumper": "^7.1",
|
||||
"vimeo/psalm": "^5.24"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\": "tests/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"ergebnis/composer-normalize": true,
|
||||
"infection/extension-installer": true
|
||||
},
|
||||
"sort-packages": true,
|
||||
"sort-scripts": false
|
||||
},
|
||||
"scripts": {
|
||||
"infection": "infection --threads=max --show-mutations",
|
||||
"normalize": "composer normalize --dry-run --diff --ansi",
|
||||
"php-cs-fixer": "php-cs-fixer fix --diff --verbose",
|
||||
"phpunit": "phpunit --colors=always --order-by=random",
|
||||
"psalm": "psalm --show-info=true --no-diff",
|
||||
"rector": "rector process",
|
||||
"require-checker": "composer-require-checker check --config-file=composer-require-checker.json composer.json",
|
||||
"tests": [
|
||||
"@validate",
|
||||
"@normalize",
|
||||
"@require-checker",
|
||||
"@unused",
|
||||
"composer php-cs-fixer -- --dry-run --diff --format=checkstyle --ansi",
|
||||
"composer rector -- --dry-run",
|
||||
"composer psalm -- --stats --shepherd",
|
||||
"@phpunit",
|
||||
"@infection"
|
||||
],
|
||||
"unused": "composer-unused --excludePackage=ext-curl",
|
||||
"validate": "composer validate --strict --ansi"
|
||||
}
|
||||
}
|
||||
7801
composer.lock
generated
Normal file
7801
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
infection.json5.dist
Normal file
19
infection.json5.dist
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "vendor/infection/infection/resources/schema.json",
|
||||
"source": {
|
||||
"directories": [
|
||||
"src"
|
||||
]
|
||||
},
|
||||
"logs": {
|
||||
"text": "var/infection.log",
|
||||
"stryker": {
|
||||
"report": "/^\\d+\\.\\d+\\.x$/"
|
||||
},
|
||||
},
|
||||
"tmpDir": "var",
|
||||
"minCoveredMsi": 20,
|
||||
"mutators": {
|
||||
"@default": true
|
||||
}
|
||||
}
|
||||
27
phpunit.xml.dist
Normal file
27
phpunit.xml.dist
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
cacheDirectory="var/phpunit"
|
||||
executionOrder="depends,defects"
|
||||
requireCoverageMetadata="true"
|
||||
beStrictAboutOutputDuringTests="true"
|
||||
failOnRisky="true"
|
||||
failOnWarning="true"
|
||||
>
|
||||
<php>
|
||||
<ini name="display_errors" value="1"/>
|
||||
<ini name="error_reporting" value="-1"/>
|
||||
</php>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="default">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true">
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</source>
|
||||
</phpunit>
|
||||
75
psalm.xml.dist
Normal file
75
psalm.xml.dist
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
cacheDirectory="var/psalm"
|
||||
checkForThrowsDocblock="true"
|
||||
checkForThrowsInGlobalScope="true"
|
||||
disableSuppressAll="true"
|
||||
ensureArrayStringOffsetsExist="true"
|
||||
errorLevel="1"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="true"
|
||||
findUnusedPsalmSuppress="true"
|
||||
findUnusedVariablesAndParams="true"
|
||||
memoizeMethodCallResults="true"
|
||||
reportMixedIssues="true"
|
||||
sealAllMethods="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<enableExtensions>
|
||||
<extension name="dom"/>
|
||||
</enableExtensions>
|
||||
|
||||
<plugins>
|
||||
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
|
||||
</plugins>
|
||||
|
||||
<projectFiles>
|
||||
<file name="app.php"/>
|
||||
<directory name="src"/>
|
||||
<directory name="tests"/>
|
||||
<ignoreFiles>
|
||||
<directory name="var"/>
|
||||
<directory name="vendor"/>
|
||||
<file name="tests/benchmark.php"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
|
||||
<ignoreExceptions>
|
||||
<classAndDescendants name="LogicException"/>
|
||||
<classAndDescendants name="RuntimeException"/>
|
||||
<classAndDescendants name="ReflectionException"/>
|
||||
</ignoreExceptions>
|
||||
|
||||
<issueHandlers>
|
||||
<MissingThrowsDocblock>
|
||||
<errorLevel type="suppress">
|
||||
<directory name="tests"/>
|
||||
</errorLevel>
|
||||
</MissingThrowsDocblock>
|
||||
<MixedAssignment errorLevel="suppress"/>
|
||||
<PossiblyUnusedMethod>
|
||||
<errorLevel type="suppress">
|
||||
<directory name="tests"/>
|
||||
</errorLevel>
|
||||
</PossiblyUnusedMethod>
|
||||
<UnusedMethodCall>
|
||||
<errorLevel type="suppress">
|
||||
<directory name="tests"/>
|
||||
</errorLevel>
|
||||
</UnusedMethodCall>
|
||||
</issueHandlers>
|
||||
|
||||
<forbiddenFunctions>
|
||||
<function name="dd"/>
|
||||
<function name="die"/>
|
||||
<function name="dump"/>
|
||||
<function name="echo"/>
|
||||
<function name="eval"/>
|
||||
<function name="exit"/>
|
||||
<function name="print"/>
|
||||
<function name="sleep"/>
|
||||
<function name="usleep"/>
|
||||
</forbiddenFunctions>
|
||||
</psalm>
|
||||
20
rector.php
Normal file
20
rector.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Set\ValueObject\LevelSetList;
|
||||
use Rector\Set\ValueObject\DowngradeLevelSetList;
|
||||
|
||||
return static function (RectorConfig $rectorConfig): void {
|
||||
$rectorConfig->parallel();
|
||||
$rectorConfig->cacheDirectory(__DIR__ . '/var/rector');
|
||||
$rectorConfig->paths([
|
||||
__DIR__ . '/src',
|
||||
__DIR__ . '/tests',
|
||||
]);
|
||||
$rectorConfig->sets([
|
||||
LevelSetList::UP_TO_PHP_83,
|
||||
// DowngradeLevelSetList::DOWN_TO_PHP_81,
|
||||
]);
|
||||
};
|
||||
@@ -1,143 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is to serve as a Plugin for Drone to enable uploading of generic packages to Gitea e.g Ansible Roles
|
||||
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
# check to see if this file is being run or sourced from another script
|
||||
_is_sourced() {
|
||||
# https://unix.stackexchange.com/a/215279
|
||||
[ "${#FUNCNAME[@]}" -ge 2 ] &&
|
||||
[ "${FUNCNAME[0]}" = '_is_sourced' ] &&
|
||||
[ "${FUNCNAME[1]}" = 'source' ]
|
||||
}
|
||||
|
||||
# logging functions
|
||||
action_log() {
|
||||
local type="$1"
|
||||
shift
|
||||
# accept argument string or stdin
|
||||
local text="$*"
|
||||
if [ "$#" -eq 0 ]; then text="$(cat)"; fi
|
||||
local dt
|
||||
dt="$(date -D 'YYYY-MM-DD hh:mm[:ss]')"
|
||||
printf '%s [%s] [gitea-composer-uploader]: %s\n' "$dt" "$type" "$text"
|
||||
}
|
||||
action_note() {
|
||||
action_log INF "$@"
|
||||
}
|
||||
action_warn() {
|
||||
action_log WRN "$@" >&2
|
||||
}
|
||||
action_error() {
|
||||
action_log ERR "$@" >&2
|
||||
}
|
||||
|
||||
# Verify that the minimally required password settings are set for operation.
|
||||
function verify_minimum_env {
|
||||
if [ -z "$username" ]; then
|
||||
action_warn "username is required for action operation"
|
||||
fi
|
||||
if [ -z "$baseurl" ]; then
|
||||
action_warn "baseurl setting is required for action operation"
|
||||
fi
|
||||
if [ -z "$owner" ]; then
|
||||
action_warn "owner setting is required for action operation"
|
||||
fi
|
||||
if [ -z "$access_token" ]; then
|
||||
action_warn "access_token setting is required for action operation"
|
||||
fi
|
||||
if [ -z "$version" ]; then
|
||||
action_warn "version setting is required for action operation"
|
||||
fi
|
||||
if [ -z "$username" ] ||
|
||||
[ -z "$baseurl" ] ||
|
||||
[ -z "$version" ] ||
|
||||
[ -z "$access_token" ]; then
|
||||
action_error <<-'EOF'
|
||||
You need to specify one/all of the following settings:
|
||||
- username
|
||||
- access_token
|
||||
- baseurl
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
action_note "Sufficient configuration"
|
||||
|
||||
}
|
||||
|
||||
function delete_file {
|
||||
no_prefix_version="${version##v}"
|
||||
username_or_owner=${owner:-$username}
|
||||
no_owner_repo_name="${GITHUB_REPOSITORY##"$username_or_owner"/}"
|
||||
# shellcheck disable=SC2154
|
||||
for file in ${upload_file}; do
|
||||
action_note "curl -s -o /dev/null -w '%{http_code}' --user \"${username}:${access_token}\" -X DELETE ${baseurl}/api/v1/packages/${owner:-$username}/composer/${owner:-$username}%2F${no_owner_repo_name}/${no_prefix_version}"
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" --user "${username}:${access_token}" -X DELETE "${baseurl}/api/v1/packages/${owner:-$username}/composer/${owner:-$username}%2F${no_owner_repo_name}/${no_prefix_version}")
|
||||
if [ "${response}" == 204 ] || [ "${response}" == 200 ]; then
|
||||
action_note "Deleted package version ${version} for ${owner:-$username}/${repo_name}"
|
||||
elif [ "${response}" == 404 ]; then
|
||||
action_error "Not Found: Odd I cannot locate your package! [bug]"
|
||||
else
|
||||
action_error "Response code was ${response}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
function process_upload_file {
|
||||
for file in ${upload_file}; do
|
||||
#action_note "curl -s -o /dev/null -w '%{http_code}' --user \"${username}:${access_token}\" --upload-file ${file} \"${baseurl}/api/packages/${owner:-$username}/composer?version=${version}\""
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" --user "${username}:${access_token}" --upload-file "${file}" "${baseurl}/api/packages/${owner:-$username}/composer?version=${version}")
|
||||
if [ "${response}" == 409 ]; then
|
||||
action_error "Conflict: File already exists"
|
||||
if [ "${FILE_OVERWRITE:=$overwrite_files}" == 'true' ]; then
|
||||
# Delete file as already exists
|
||||
delete_file
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" --user "${username}:${access_token}" --upload-file "${file}" "${baseurl}/api/packages/${owner:-$username}/composer?version=${version}")
|
||||
if [ "${response}" == 409 ]; then
|
||||
action_error "Conflict: File already exists"
|
||||
elif [ "${response}" == 201 ]; then
|
||||
action_note "File uploaded successfully"
|
||||
elif [ "${response}" == 400 ]; then
|
||||
action_error "Bad Request: Version likely already exists"
|
||||
fi
|
||||
else
|
||||
action_error 'Unable to upload file. Maybe toggle overwrite_files setting to true :)'
|
||||
exit 1
|
||||
fi
|
||||
elif [ "${response}" == 201 ]; then
|
||||
action_note "File uploaded successfully"
|
||||
elif [ "${response}" == 400 ]; then
|
||||
action_warn "Bad Request: Version likely already exists"
|
||||
if [ "${FILE_OVERWRITE:=$overwrite_files}" == 'true' ]; then
|
||||
# Delete file as already exists
|
||||
delete_file
|
||||
response=$(curl -s -o /dev/null -w "%{http_code}" --user "${username}:${access_token}" --upload-file "${file}" "${baseurl}/api/packages/${owner:-$username}/composer?version=${version}")
|
||||
if [ "${response}" == 409 ]; then
|
||||
action_error "Conflict: File already exists"
|
||||
elif [ "${response}" == 201 ]; then
|
||||
action_note "File uploaded successfully"
|
||||
elif [ "${response}" == 400 ]; then
|
||||
action_error "Bad Request: Version likely already exists"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
action_error 'Unable to upload file. Maybe toggle overwrite_files setting to true :)'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
_main() {
|
||||
action_note "Starting"
|
||||
verify_minimum_env "$@"
|
||||
process_upload_file "$@"
|
||||
}
|
||||
|
||||
# If we are sourced from elsewhere, don't perform any further actions
|
||||
if ! _is_sourced; then
|
||||
_main "$@"
|
||||
fi
|
||||
0
src/.gitkeep
Normal file
0
src/.gitkeep
Normal file
37
src/Action.php
Normal file
37
src/Action.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App;
|
||||
|
||||
use App\Configuration\Configuration;
|
||||
|
||||
final class Action
|
||||
{
|
||||
private Configuration $configuration;
|
||||
|
||||
public function __construct(Configuration $configuration)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$this->checkExtensions();
|
||||
$this->checkConfiguration();
|
||||
|
||||
// $this->configuration->getCastingType('param', MapperType::STRING)->getAsCasting()
|
||||
}
|
||||
|
||||
private function checkExtensions(): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private function checkConfiguration(): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
10
src/Casting/Casting.php
Normal file
10
src/Casting/Casting.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting;
|
||||
|
||||
interface Casting
|
||||
{
|
||||
public function getAsCasting(): mixed;
|
||||
}
|
||||
46
src/Casting/MapperType.php
Normal file
46
src/Casting/MapperType.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting;
|
||||
|
||||
use App\Casting\Type\IntegerType;
|
||||
use App\Casting\Type\StringType;
|
||||
use App\Casting\Type\Type;
|
||||
use App\Exception\Casting\TypeNotFountException;
|
||||
|
||||
final readonly class MapperType
|
||||
{
|
||||
public const string STRING = 'string';
|
||||
public const string INTEGER = 'integer';
|
||||
public const string INT = 'int';
|
||||
private const array MAP = [
|
||||
self::STRING => StringType::class,
|
||||
self::INTEGER => IntegerType::class,
|
||||
self::INT => IntegerType::class,
|
||||
];
|
||||
|
||||
private string $class;
|
||||
|
||||
/**
|
||||
* @throws TypeNotFountException
|
||||
*/
|
||||
public function __construct(string $type)
|
||||
{
|
||||
if (!isset(self::MAP[$type])) {
|
||||
throw new TypeNotFountException(
|
||||
\sprintf('Casting type "%s" is not found.', $type),
|
||||
);
|
||||
}
|
||||
|
||||
$this->class = self::MAP[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(mixed $value): Type
|
||||
{
|
||||
return new $this->class($value);
|
||||
}
|
||||
}
|
||||
21
src/Casting/Type/AbstractType.php
Normal file
21
src/Casting/Type/AbstractType.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting\Type;
|
||||
|
||||
use App\Casting\Casting;
|
||||
|
||||
abstract class AbstractType implements Type, Casting
|
||||
{
|
||||
public function __construct(protected mixed $value) {}
|
||||
|
||||
#[\Override]
|
||||
final public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
abstract public function getAsCasting(): mixed;
|
||||
}
|
||||
14
src/Casting/Type/IntegerType.php
Normal file
14
src/Casting/Type/IntegerType.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting\Type;
|
||||
|
||||
final class IntegerType extends AbstractType
|
||||
{
|
||||
#[\Override]
|
||||
public function getAsCasting(): int
|
||||
{
|
||||
return (int) $this->getValue();
|
||||
}
|
||||
}
|
||||
14
src/Casting/Type/StringType.php
Normal file
14
src/Casting/Type/StringType.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting\Type;
|
||||
|
||||
final class StringType extends AbstractType
|
||||
{
|
||||
#[\Override]
|
||||
public function getAsCasting(): string
|
||||
{
|
||||
return (string) $this->getValue();
|
||||
}
|
||||
}
|
||||
10
src/Casting/Type/Type.php
Normal file
10
src/Casting/Type/Type.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting\Type;
|
||||
|
||||
interface Type
|
||||
{
|
||||
public function getValue();
|
||||
}
|
||||
39
src/Configuration/Configuration.php
Normal file
39
src/Configuration/Configuration.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Configuration;
|
||||
|
||||
use App\Casting\MapperType;
|
||||
use App\Casting\Type\Type;
|
||||
use App\Exception\Casting\TypeNotFountException;
|
||||
|
||||
final class Configuration
|
||||
{
|
||||
public array $options = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function set(string $key, mixed $value): self
|
||||
{
|
||||
$this->options[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function get(string $key): mixed
|
||||
{
|
||||
return $this->options[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws TypeNotFountException
|
||||
*/
|
||||
public function getCastingType(string $key, string $type): Type
|
||||
{
|
||||
return (new MapperType($type))->create($this->get($key));
|
||||
}
|
||||
}
|
||||
9
src/Exception/Casting/TypeNotFountException.php
Normal file
9
src/Exception/Casting/TypeNotFountException.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception\Casting;
|
||||
|
||||
use App\Exception\Exception;
|
||||
|
||||
final class TypeNotFountException extends Exception {}
|
||||
7
src/Exception/Exception.php
Normal file
7
src/Exception/Exception.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
class Exception extends \Exception {}
|
||||
52
tests/Casting/MapperTypeTest.php
Normal file
52
tests/Casting/MapperTypeTest.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Casting;
|
||||
|
||||
use App\Casting\Type\IntegerType;
|
||||
use App\Casting\Type\StringType;
|
||||
use App\Exception\Casting\TypeNotFountException;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(MapperType::class)]
|
||||
final class MapperTypeTest extends TestCase
|
||||
{
|
||||
public function testGetStringType(): void
|
||||
{
|
||||
$type = (new MapperType(MapperType::STRING))->create('value');
|
||||
|
||||
self::assertInstanceOf(
|
||||
StringType::class,
|
||||
$type,
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetIntegerType(): void
|
||||
{
|
||||
$type = (new MapperType(MapperType::INTEGER))->create(1);
|
||||
|
||||
self::assertInstanceOf(
|
||||
IntegerType::class,
|
||||
$type,
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetIntType(): void
|
||||
{
|
||||
$type = (new MapperType(MapperType::INT))->create(1);
|
||||
|
||||
self::assertInstanceOf(
|
||||
IntegerType::class,
|
||||
$type,
|
||||
);
|
||||
}
|
||||
|
||||
public function testTypeNotFountException(): void
|
||||
{
|
||||
self::expectException(TypeNotFountException::class);
|
||||
|
||||
(new MapperType('type-exception'))->create('value');
|
||||
}
|
||||
}
|
||||
23
tests/Configuration/ConfigurationTest.php
Normal file
23
tests/Configuration/ConfigurationTest.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Configuration;
|
||||
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
#[CoversClass(Configuration::class)]
|
||||
final class ConfigurationTest extends TestCase
|
||||
{
|
||||
public function testUseConfiguration(): void
|
||||
{
|
||||
$configuration = new Configuration();
|
||||
$configuration->set('test-option', 'test-value');
|
||||
|
||||
self::assertEquals(
|
||||
$configuration->get('test-option'),
|
||||
'test-value',
|
||||
);
|
||||
}
|
||||
}
|
||||
1
tests/benchmark.php
Normal file
1
tests/benchmark.php
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
2
var/.gitignore
vendored
Normal file
2
var/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
Reference in New Issue
Block a user