From 7de01366fad519e6188a9e0aa80709e74b5e9133 Mon Sep 17 00:00:00 2001 From: Alex Skrypnyk Date: Fri, 23 Feb 2024 07:14:21 +1100 Subject: [PATCH] [#48] Added GHA example. --- .circleci/config.yml | 20 +++-- .github/workflows/test-php.yml | 136 +++++++++++++++++++++++++++++++++ README.md | 53 ++++++++++--- composer.json | 3 +- 4 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/test-php.yml diff --git a/.circleci/config.yml b/.circleci/config.yml index b9b5827..9273688 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,31 +56,41 @@ jobs: - *deploy_ssh_fingerprint - *step_setup_git - checkout - - run: - name: Create test asset file. - command: touch test-file-$(date "+%Y%m%d-%H%M%S").txt - run: name: Demonstration of deployment in 'force-push' mode. command: | + TEST_FILE="test-file-force-push-circleci-$(date "+%Y%m%d-%H%M%S").txt" + touch $TEST_FILE + vendor/bin/robo artifact \ git@github.com:drevops/git-artifact-destination.git \ + --branch=mode-force-push-circleci \ --mode=force-push \ - --branch=mode-force-push \ --report=$HOME/report-mode-force-push.txt \ --push + DEPLOY_BRANCH=$(sed -n 's/Remote branch://p' $HOME/report-mode-force-push.txt | sed 's/ //g') echo "Deployed to $DEPLOY_BRANCH" + echo + echo "See https://github.com/drevops/git-artifact-destination/blob/$DEPLOY_BRANCH/$TEST_FILE" + - run: name: Demonstration of deployment in 'branch' mode. command: | + TEST_FILE="test-file-branch-circleci-$(date "+%Y%m%d-%H%M%S").txt" + touch $TEST_FILE + vendor/bin/robo artifact \ git@github.com:drevops/git-artifact-destination.git \ + --branch=mode-branch-circleci-[timestamp:Y-m-d_H-i-s] \ --mode=branch \ - --branch=mode-branch-[timestamp:Y-m-d_H-i-s] \ --report=$HOME/report-mode-branch.txt \ --push + DEPLOY_BRANCH=$(sed -n 's/Remote branch://p' $HOME/report-mode-branch.txt | sed 's/ //g') echo "Deployed to $DEPLOY_BRANCH" + echo + echo "See https://github.com/drevops/git-artifact-destination/blob/$DEPLOY_BRANCH/$TEST_FILE" workflows: version: 2 diff --git a/.github/workflows/test-php.yml b/.github/workflows/test-php.yml new file mode 100644 index 0000000..364b32b --- /dev/null +++ b/.github/workflows/test-php.yml @@ -0,0 +1,136 @@ +name: Test PHP + +on: + push: + branches: + - main + pull_request: + branches: + - main + - 'feature/**' + +jobs: + test-php: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.1', '8.2', '8.3'] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: /tmp/composer-cache + key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Setup SSH private key + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} + + - name: Configure Git + run: | + git config --global user.name "${{ secrets.DEPLOY_USER_NAME }}" + git config --global user.email "${{ secrets.DEPLOY_USER_EMAIL }}" + + - name: Install dependencies + run: composer install + + - name: Check coding standards + run: composer lint + + - name: Run tests + run: XDEBUG_MODE=coverage composer test + + - name: Upload coverage report as an artifact + uses: actions/upload-artifact@v4 + with: + name: ${{github.job}}-code-coverage-report-${{ matrix.php-versions }} + path: ./.coverage-html + + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v4 + with: + files: ./cobertura.xml + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + + deploy: + needs: test-php + + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: /tmp/composer-cache + key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Setup SSH private key + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} + + - name: Configure Git + run: | + git config --global user.name "${{ secrets.DEPLOY_USER_NAME }}" + git config --global user.email "${{ secrets.DEPLOY_USER_EMAIL }}" + + - name: Install dependencies + run: composer install + + - name: Demonstration of deployment in 'force-push' mode. + run: | + TEST_FILE="test-file-force-push-github-$(date "+%Y%m%d-%H%M%S").txt" + touch $TEST_FILE + + vendor/bin/robo artifact \ + git@github.com:drevops/git-artifact-destination.git \ + --branch=mode-force-push-github \ + --mode=force-push \ + --report=$HOME/report-mode-force-push.txt \ + --push + + DEPLOY_BRANCH=$(sed -n 's/Remote branch://p' $HOME/report-mode-force-push.txt | sed 's/ //g') + echo "Deployed to $DEPLOY_BRANCH" + echo + echo "See https://github.com/drevops/git-artifact-destination/blob/$DEPLOY_BRANCH/$TEST_FILE" + + - name: Demonstration of deployment in 'branch' mode. + run: | + TEST_FILE="test-file-branch-github-$(date "+%Y%m%d-%H%M%S").txt" + touch $TEST_FILE + + vendor/bin/robo artifact \ + git@github.com:drevops/git-artifact-destination.git \ + --branch=mode-branch-github-[timestamp:Y-m-d_H-i-s] \ + --mode=branch \ + --report=$HOME/report-mode-branch.txt \ + --push + + DEPLOY_BRANCH=$(sed -n 's/Remote branch://p' $HOME/report-mode-branch.txt | sed 's/ //g') + echo "Deployed to $DEPLOY_BRANCH" + echo + echo "See https://github.com/drevops/git-artifact-destination/blob/$DEPLOY_BRANCH/$TEST_FILE" diff --git a/README.md b/README.md index 7c12841..4ad34f3 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,11 @@

## What is it? + Build artifact from your codebase in CI and push it to a separate git repo. ## Why? + Some hosting providers, like Acquia, have limitation on the languages or frameworks required to build applications (for example, running `composer install` is not possible due to read-only file system). This means @@ -43,10 +45,13 @@ Since destination repository requires a commit to add changes introduced by the artifact files (CSS, JS, etc.), there are 2 modes to make this commit: "force-push" and "branch". -See example of deployed artifact in [Artefact branches](https://github.com/drevops/git-artifact-destination/branches). +See example of deployed artifact +in [Artefact branches](https://github.com/drevops/git-artifact-destination/branches). ## Modes + ### Force-push mode (default) + Push packaged artifact to the same branch, preserving the history from the source repository, but overwriting history in destination repository on each push. @@ -56,6 +61,7 @@ push. ![diagram of force-push mode](https://user-images.githubusercontent.com/378794/33816665-a7b0e4a8-de8e-11e7-88f2-80baefb3d73f.png) ### Branch mode + Push packaged artifact to the new branch on each deployment, preserving history from the source repository, but requiring to trigger a deployment of newly created branch after each deployment. @@ -64,13 +70,12 @@ created branch after each deployment. ![diagram of branch mode](https://user-images.githubusercontent.com/378794/33816666-a87b3910-de8e-11e7-82cd-51e007ece063.png) - ## Installation composer require --dev -n --ansi --prefer-source --ignore-platform-reqs drevops/git-artifact - ## Usage + Use provided [`RoboFile.php`](RoboFile.php) or crearte a custom `RoboFile.php` in your repository with the following content: @@ -104,21 +109,32 @@ specified remote repository into the same branch as a current one. ### Run in CI +See examples: + +- [GitHub Actions](.github/workflows/test-php.yml) +- [CircleCI](.circleci/config.yml) + Fill-in these variables trough UI or in deployment script. # Remote repository to push artifact to. DEPLOY_REMOTE="${DEPLOY_REMOTE:-}" + # Remote repository branch. Can be a specific branch or a token. DEPLOY_BRANCH="${DEPLOY_BRANCH:-[branch]}" + # Source of the code to be used for artifact building. DEPLOY_SRC="${DEPLOY_SRC:-}" + # The root directory where the deployment script should run from. Defaults to # the current directory. DEPLOY_ROOT="${DEPLOY_ROOT:-$(pwd)}" + # Deployment report file name. DEPLOY_REPORT="${DEPLOY_REPORT:-${DEPLOY_ROOT}/deployment_report.txt}" + # Email address of the user who will be committing to a remote repository. DEPLOY_USER_NAME="${DEPLOY_USER_NAME:-"Deployer Robot"}" + # Name of the user who will be committing to a remote repository. DEPLOY_USER_EMAIL="${DEPLOY_USER_EMAIL:-deployer@example.com}" @@ -133,7 +149,8 @@ Call from CI configuration or deployment script: --report="${DEPLOY_REPORT}" \ --push -See extended and fully-configured [example in the DrevOps project](https://github.com/drevops/drevops/blob/develop/scripts/drevops/deploy-artifact.sh). +See extended and +fully-configured [example in the DrevOps project](https://github.com/drevops/drevops/blob/develop/scripts/drevops/deploy-artifact.sh). ## Options @@ -169,31 +186,47 @@ See extended and fully-configured [example in the DrevOps project](https://githu Help: Push artifact of current repository to remote git repository. - ### Adding dependencies -`--gitignore` option allows to specify the path to the _artifact gitignore_ file that replaces existing _.gitignore_ (if any) during the build. Any files no longer ignored by the replaced _artifact gitignore_ are added into the _deployment commit_. If there are no no-longer-excluded files, the _deployment commit_ is still created, to make sure that the deployment timestamp is captured. + +`--gitignore` option allows to specify the path to the _artifact gitignore_ file +that replaces existing _.gitignore_ (if any) during the build. Any files no +longer ignored by the replaced _artifact gitignore_ are added into the +_deployment commit_. If there are no no-longer-excluded files, the _deployment +commit_ is still created, to make sure that the deployment timestamp is +captured. ### Token support -Both `--branch` and `--message` option values support token replacement. Tokens are pre-defined strings surrounded by `[` and `]` and may contain optional formatter (for flexibility). For example, `[timestamp:Y-m-d]` is replaced with current timestamp in format `Y-m-d` (token formatter), which is PHP `date()` expected format. + +Both `--branch` and `--message` option values support token replacement. Tokens +are pre-defined strings surrounded by `[` and `]` and may contain optional +formatter (for flexibility). For example, `[timestamp:Y-m-d]` is replaced with +current timestamp in format `Y-m-d` (token formatter), which is PHP `date()` +expected format. Available tokens: + - `[timestamp:FORMAT]` - current time with a PHP `date()`-compatible format. - `[branch]` - current `source` branch. - `[tags]` - tags from latest `_source` commit (if any), separated by comma. ## Examples + ### Push branch to the same remote robo artifact git@myserver.com/repository.git --push -In this example, all commits in the repository will be pushed to the same branch as current one with all processed files (assets etc.) captured in the additional deployment commit. `--push` flag enables actual pushing into remote repository. - +In this example, all commits in the repository will be pushed to the same branch +as current one with all processed files (assets etc.) captured in the additional +deployment commit. `--push` flag enables actual pushing into remote repository. ### Push release branches created from tags robo artifact git@myserver.com/repository.git --mode=branch --branch=release/[tags:-] --push -In this example, if the latest commit was tagged with tag `1.2.0`, the artifact will be pushed to the branch `release/1.2.0`. If there latest commit is tagged with multiple tags - they will be glued to gether with delimiter `-`, which would reult in the branch name `release/1.2.0-secondtag`. +In this example, if the latest commit was tagged with tag `1.2.0`, the artifact +will be pushed to the branch `release/1.2.0`. If there latest commit is tagged +with multiple tags - they will be glued to gether with delimiter `-`, which +would reult in the branch name `release/1.2.0-secondtag`. ## Maintenance diff --git a/composer.json b/composer.json index 969ee6c..dd9730c 100644 --- a/composer.json +++ b/composer.json @@ -33,8 +33,7 @@ "phpstan" ], "lint:fix": "phpcbf", - "test": "phpunit --no-coverage", - "test:coverage": "XDEBUG_MODE=coverage phpunit" + "test": "if [ \"${XDEBUG_MODE}\" = 'coverage' ]; then phpunit; else phpunit --no-coverage; fi" }, "autoload": { "psr-4": {