name: 'Code - Create new release' on: workflow_dispatch: inputs: version: description: 'Release "v1.2.3" or "develop" or "branch-abc"' required: true default: 'develop' phpversion: description: 'PHP version' required: true default: '8.4' schedule: - cron: '0 3 * * MON' jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v5 with: fetch-depth: 0 - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.PASSPHRASE }} git_user_signingkey: true git_commit_gpgsign: true - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ github.event.inputs.phpversion }} extensions: mbstring, intl, zip, bcmath - name: Switch and pull run: | # # Always check out origin/develop, unless its a branch release. # BRANCH_TO_PULL=origin/develop if [[ "$version" == branch* ]]; then BRANCH_TO_PULL=origin/$version fi echo "Version is '$version', check out '$BRANCH_TO_PULL'-branch" git checkout --track $BRANCH_TO_PULL git pull echo "Current branch is $(git branch --show-current)" env: version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Configure Git run: | # do some configuration sudo timedatectl set-timezone Europe/Amsterdam git config user.name JC5 git config user.email release@firefly-iii.org git config advice.addIgnoredFile false git config push.autoSetupRemote true - name: Lint PHP run: | php_lint_file() { local php_file="$1" php -l "$php_file" &> /dev/null if [ "$?" -ne 0 ] then echo -e "[FAIL] $php_file" return 1 fi } export -f php_lint_file find . -path ./vendor -prune -o -name '*.php' | parallel -j 4 php_lint_file {} if [ "$?" -ne 0 ] then exit 1 fi - name: Crowdin action uses: crowdin/github-action@v2 with: upload_sources: true download_translations: true push_translations: false push_sources: false env: GITHUB_TOKEN: ${{ github.token }} CROWDIN_PROJECT_NR: ${{ secrets.CROWDIN_PROJECT_NR }} CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }} - name: Cleanup changelog id: cleanup-changelog uses: JC5/firefly-iii-dev@main with: action: 'ff3:changelog' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: ${{ secrets.CHANGELOG_TOKEN }} - name: "Create THANKS.md" id: thank-you uses: JC5/firefly-iii-dev@main with: action: 'ff3:thank-you' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: '' - name: Replace version id: replace-version uses: JC5/firefly-iii-dev@main with: action: 'ff3:version' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: "" FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Generate JSON v1 id: json-v1 uses: JC5/firefly-iii-dev@main with: action: 'ff3:json-translations v1' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: '' - name: Generate JSON v2 id: json-v2 uses: JC5/firefly-iii-dev@main with: action: 'ff3:json-translations v2' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: '' - name: Code cleanup id: code-cleanup uses: JC5/firefly-iii-dev@main with: action: 'ff3:code' output: '' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: '' - name: Build JS run: | npm install npm run prod --workspace=v1 npm run build --workspace=v2 npm update - name: Run CI run: | rm -rf vendor composer.lock composer update --no-dev --no-scripts --no-plugins -q sudo chown -R runner:docker resources/lang .ci/phpcs.sh || true - name: Calculate variables run: | # set some variables releaseName=$version originalName=$version zipName=FireflyIII-$version.zip tarName=FireflyIII-$version.tar.gz # if this is a develop build, slightly different variable names. if [[ "develop" == "$version" ]]; then #[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; releaseName=$version-$(date +'%Y%m%d') originalName=$releaseName zipName=FireflyIII-develop.zip tarName=FireflyIII-develop.tar.gz fi # if this is a branch build, also slightly different variable names. if [[ "$version" == branch* ]]; then #[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; # branch builds overrule develop releaseName=$version-$(date +'%Y%m%d') originalName=$releaseName zipName=FireflyIII-$version.zip tarName=FireflyIII-$version.tar.gz fi # in both cases, if the release or tag already exists, add ".1" until it no longer exists. tagFound=true tagCount=1 while [ "$tagFound" = true ] do if [ $(git tag -l "$releaseName") ]; then echo "Tag $releaseName exists already." releaseName="$originalName"."$tagCount" echo "Tag for release is now $releaseName" tagCount=$((tagCount+1)) else echo "Tag $releaseName does not exist, can continue" tagFound=false fi done # set some variables echo "Release name is $releaseName." echo "Original name is $originalName." echo "Zip name is $zipName." echo "Tar name is $tarName." # create a new branch to store the difference in. BRANCH_NAME=release-$(date +'%s') git checkout -b $BRANCH_NAME echo "Temporary branch name is '$BRANCH_NAME'." # share variables with next step. echo "releaseName=$releaseName" >> "$GITHUB_ENV" echo "originalName=$originalName" >> "$GITHUB_ENV" echo "zipName=$zipName" >> "$GITHUB_ENV" echo "tarName=$tarName" >> "$GITHUB_ENV" echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV" env: version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Commit all changes run: | # add all content, except output.txt (this contains the changelog and/or the download instructions) echo 'Add all' git add -A # push to a new branch. echo "Auto commit on branch '$(git branch --show-current)'." git commit -m "🤖 Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true git push env: version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Generate release description id: release-description uses: JC5/firefly-iii-dev@main with: action: "ff3:generate-release-notes firefly-iii ${{ inputs.version || 'develop' }}" output: 'output' env: FIREFLY_III_ROOT: /github/workspace GH_TOKEN: "" - name: Merge all into working branch run: | MERGE_INTO=develop if [[ "$version" == branch* ]]; then MERGE_INTO=$version fi echo "Merge all changes from $BRANCH_NAME back into '$MERGE_INTO' using a PR" PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`') echo "PR URL is '$PR_URL'" IFS='/' read -ra parts <<< "$PR_URL" PR_NR=$(printf %s\\n "${parts[@]:(-1)}") echo "PR number is '$PR_NR'" gh pr merge $PR_NR -b "🤖 Automatically merge the PR into the $MERGE_INTO branch." -d --merge # pull the changes from the $MERGE_INTO branch. git checkout $MERGE_INTO git merge origin/$MERGE_INTO git pull git status echo "Current branch '$(git branch --show-current)'." if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]]; then git checkout main git merge origin/main git pull git status echo "Also merge everything into main since this is a release." echo 'create PR' PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`') echo "PR URL is '$PR_URL'" IFS='/' read -ra parts <<< "$PR_URL" PR_NR=$(printf %s\\n "${parts[@]:(-1)}") echo "PR number is '$PR_NR'" echo 'Merge PR' gh pr merge $PR_NR -b "🤖 Automatically merge the PR into the main branch." --merge git checkout main git merge origin/main git pull git status echo "Current branch '$(git branch --show-current)'." fi echo "DONE!" env: GH_TOKEN: ${{ github.token }} version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Create archives run: | echo "Create zip file $zipName" zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*" "*Procfile*" "*crowdin.yml*" "*sonar-project.properties*" touch $tarName echo "Create tar file $tarName" tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' --exclude='./Procfile' --exclude='../crowdin.yml' --exclude='./sonar-project.properties' -czf $tarName . # add sha256 sum echo 'Sha sum ...' sha256sum -b $zipName > $zipName.sha256 sha256sum -b $tarName > $tarName.sha256 # add signatures: gpg --armor --detach-sign $zipName gpg --armor --detach-sign $tarName - name: Create release run: | # create a development release: if [[ "develop" == "$version" ]]; then # pull the changes from the develop branch. git checkout develop git merge origin/develop git pull # create the release: echo "Create develop release under tag '$releaseName'." git tag -a $releaseName -m "🤖 Development release '$version' on $(date +'%Y-%m-%d')" git push origin $releaseName gh release create $releaseName -p --verify-tag \ -t "Development release for $(date +'%Y-%m-%d')" \ --latest=false \ -F output.txt fi # create a branch release: if [[ "$version" == branch* ]]; then # pull the changes from the branch-* branch. git checkout $version git merge origin/$version git pull # create the release: echo "Create branch release." git tag -a $releaseName -m "Branch release '$version' on $(date +'%Y-%m-%d')" git push origin $releaseName gh release create $releaseName -p --verify-tag \ -t "Branch release for $(date +'%Y-%m-%d')" \ --latest=false \ -F output.txt fi # Create a production release. if [[ "develop" != "$version" ]] && [[ "$version" != branch* ]]; then git checkout main git merge origin/main git pull git status echo "Create prod release." git tag -a $releaseName -m "Release $version" git push origin $releaseName # do not tag as latest when alpha or beta. if [[ "$version" == *alpha* ]] || [[ "$version" == *beta* ]]; then echo 'Mark alpha or beta as NOT the latest.' gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag --latest=false fi # tag as latest when NOT alpha or beta. if [[ "$version" != *alpha* ]] && [[ "$version" != *beta* ]]; then echo 'Mark prod as the latest.' gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag --latest=true fi fi env: GH_TOKEN: ${{ github.token }} version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }} - name: Upload artifacts run: | # add zip file to release. echo "Upload $zipName to $releaseName" gh release upload $releaseName $zipName echo "Upload $tarName to $releaseName" gh release upload $releaseName $tarName # add sha256 sum to release echo "Upload $zipName.sha256 to $releaseName" gh release upload $releaseName $zipName.sha256 echo "Upload $tarName.sha256 to $releaseName" gh release upload $releaseName $tarName.sha256 # add signatures to release echo "Upload $zipName.asc to $releaseName" gh release upload $releaseName $zipName.asc echo "Upload $tarName.asc to $releaseName" gh release upload $releaseName $tarName.asc # get current HEAD and add as file to the release HEAD=$(git rev-parse HEAD) echo $HEAD > HEAD.txt echo "Upload HEAD.txt to $releaseName" gh release upload $releaseName HEAD.txt # remove all temporary files rm -f output.txt rm -f HEAD.txt rm -f $zipName rm -f $zipName.sha256 rm -f $tarName rm -f $tarName.sha256 env: GH_TOKEN: ${{ github.token }} version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}