Skip to content

CI

CI #667

name: CI
on:
schedule:
# Check for update every day at 07:11
- cron: '11 7 * * *'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
WORKING_BRANCH: ci/${{ github.ref_name }}
PR_BRANCH: pr/ci/${{ github.ref_name }}
concurrency:
# Github Actions does not support ${{ env.WORKING_BRANCH }} as group name...
group: ci/${{ github.ref_name }}
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: "bottle-components-repository"
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: Create or reset ${{ env.WORKING_BRANCH }}
working-directory: "bottle-components-repository"
shell: bash {0}
run: |
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
pr_already_exists=$(gh pr list --app 'github-actions' --head ${{ env.PR_BRANCH }} --base ${{ github.ref_name }} --state 'open' --json number --jq '.[] | .[]')
if ! [ -z "$pr_already_exists" ]; then
declare -a BranchArray=( "${{ env.PR_BRANCH }}" "${{ env.WORKING_BRANCH }}" )
status=0
for BRANCH in ${BranchArray[@]}; do
git checkout $BRANCH
git rebase ${{ github.ref_name }}
status=$?
if [ $status -eq 0 ]; then
git push -f origin $BRANCH
else
break
fi
done
if [ $status -eq 0 ]; then
exit 0
fi
fi
git reset --hard ${{ github.ref_name }}
git checkout -B ${{ env.PR_BRANCH }}
git push -f --set-upstream origin ${{ env.PR_BRANCH }}
git checkout -B ${{ env.WORKING_BRANCH }}
mkdir patch_dir
touch patch_dir/.gitkeep
git add patch_dir/.gitkeep
git commit -m "Add .gitkeep file"
git push -f --set-upstream origin ${{ env.WORKING_BRANCH }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pull:
needs: prepare
strategy:
fail-fast: false
matrix:
components: [
{order: 1 , repo : "doitsujin/dxvk" , project-id: 0 , workflow: "artifacts.yml" , branch: "master", name-prefix: "dxvk-" , name-suffix: "" , version-prefix: "v" , Category: "dxvk" , Sub-category: "" , yaml-file: "14-dxvk.yml" },
{order: 2 , repo : "HansKristian-Work/vkd3d-proton" , project-id: 0 , workflow: "artifacts.yml" , branch: "master", name-prefix: "vkd3d-proton-" , name-suffix: "" , version-prefix: "v" , Category: "vkd3d" , Sub-category: "" , yaml-file: "13-vkd3d-proton.yml" },
{order: 3 , repo : "bottlesdevs/wine" , project-id: 0 , workflow: "" , branch: "soda" , name-prefix: "soda-" , name-suffix: "" , version-prefix: "soda-" , Category: "runners" , Sub-category: "wine" , yaml-file: "3-soda.yml" },
{order: 4 , repo : "bottlesdevs/wine" , project-id: 0 , workflow: "" , branch: "caffe" , name-prefix: "caffe-" , name-suffix: "" , version-prefix: "caffe-" , Category: "runners" , Sub-category: "wine" , yaml-file: "4-caffe.yml" },
{order: 5 , repo : "GloriousEggroll/wine-ge-custom" , project-id: 0 , workflow: "" , branch: "master", name-prefix: "wine-" , name-suffix: "" , version-prefix: "" , Category: "runners" , Sub-category: "wine" , yaml-file: "5-wine-GE-Proton.yml"},
{order: 6 , repo : "GloriousEggroll/proton-ge-custom", project-id: 0 , workflow: "" , branch: "master", name-prefix: "GE-Proton" , name-suffix: "" , version-prefix: "GE-Proton", Category: "runners" , Sub-category: "proton", yaml-file: "10-GE-Proton.yml" },
{order: 7 , repo : "ishitatsuyuki/LatencyFleX" , project-id: 0 , workflow: "artifact.yml" , branch: "master", name-prefix: "latencyflex-" , name-suffix: "" , version-prefix: "" , Category: "latencyflex", Sub-category: "" , yaml-file: "17-latencyflex.yml" },
{order: 8 , repo : "jp7677/dxvk-nvapi" , project-id: 0 , workflow: "artifacts.yml" , branch: "master", name-prefix: "dxvk-nvapi-" , name-suffix: "" , version-prefix: "" , Category: "nvapi" , Sub-category: "" , yaml-file: "16-dxvk-nvapi.yml" },
{order: 9 , repo : "Sporif/dxvk-async" , project-id: 0 , workflow: "" , branch: "master", name-prefix: "dxvk-async-" , name-suffix: "" , version-prefix: "" , Category: "dxvk" , Sub-category: "" , yaml-file: "15-dxvk-async.yml" },
{order: 10, repo : "Kron4ek/Wine-Builds" , project-id: 0 , workflow: "" , branch: "master", name-prefix: "wine-" , name-suffix: "-staging-tkg-amd64", version-prefix: "" , Category: "runners" , Sub-category: "wine" , yaml-file: "11-kron4ek.yml" },
{order: 11, repo : "Kron4ek/Wine-Builds" , project-id: 0 , workflow: "" , branch: "master", name-prefix: "wine-" , name-suffix: "-staging-amd64" , version-prefix: "" , Category: "runners" , Sub-category: "wine" , yaml-file: "11-kron4ek.yml" },
{order: 12, repo : "Kron4ek/Wine-Builds" , project-id: 0 , workflow: "" , branch: "master", name-prefix: "wine-" , name-suffix: "-amd64" , version-prefix: "" , Category: "runners" , Sub-category: "wine" , yaml-file: "11-kron4ek.yml" },
{order: 13, repo : "bottlesdevs/runtime" , project-id: 0 , workflow: "" , branch: "main" , name-prefix: "runtime-" , name-suffix: "" , version-prefix: "" , Category: "runtimes" , Sub-category: "" , yaml-file: "1-runtime.yml" },
{order: 14, repo : "Ph42oN/dxvk-gplasync" , project-id: 43488626, workflow: "" , branch: "main" , name-prefix: "dxvk-gplasync-", name-suffix: "" , version-prefix: "" , Category: "dxvk" , Sub-category: "" , yaml-file: "15-dxvk-async.yml" },
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: "bottle-components-repository"
ref: ${{ env.PR_BRANCH }}
- uses: actions/setup-python@v4
with:
python-version: '3.x'
cache: 'pip'
cache-dependency-path: 'bottle-components-repository/input_files/requirements-dev.txt'
# Also needs python3-pip, zstd, gawk and gh packages which are pre-installed
- run: pip install -r bottle-components-repository/input_files/requirements-dev.txt
- name: Check for new release
id: check-release
shell: bash {0}
run: |
if [ ${{ matrix.components.project-id }} -ne 0 ]; then
gitlab_json=$(curl -s https://gitlab.com/api/v4/projects/${{ matrix.components.project-id }}/releases)
latest_release=$(echo -E "$gitlab_json" | jq -r ".[] | select(.tag_name | startswith(\"${{ matrix.components.version-prefix }}\")) | .tag_name" | head -1)
else
latest_release=$(gh release list -R ${{ matrix.components.repo }} | grep -m1 "${{ matrix.components.version-prefix }}" | awk '{print $(NF-1)}')
fi
if [ -z "$latest_release" ]; then
echo "::error::Cannot find release tag begining by: ${{ matrix.components.version-prefix }}"
exit 1
fi
asset_name=" "
found=false
i=-1
until [ -z "$asset_name" ] || [ "$asset_name" = null ] || [ "$found" = true ]; do
i=$((i + 1))
if [ ${{ matrix.components.project-id }} -ne 0 ]; then
asset_name=$(echo -E "$gitlab_json" | jq -r ".[] | if .tag_name == \"$latest_release\" then . else empty end | .assets | .links | .[$i] | .name")
else
asset_name=$(gh release view "$latest_release" --json assets -q ".[] | .[$i] | .name" -R ${{ matrix.components.repo }})
fi
if [[ "$asset_name" =~ ${{ matrix.components.name-prefix }}.*[0-9]+${{ matrix.components.name-suffix }}\.tar.* ]]; then
found=true
fi
done
if [ "$found" = false ]; then
echo "::error::Cannot find a corresponding asset name."
exit 1
else
if [ ${{ matrix.components.project-id }} -ne 0 ]; then
timestamp=$(echo -E "$gitlab_json" | jq -r ".[] | if .tag_name == \"$latest_release\" then . else empty end | .created_at")
asset_json_raw=$(echo -E "$gitlab_json" | jq -r ".[] | if .tag_name == \"$latest_release\" then . else empty end | .assets | .links | .[$i]")
asset_json_raw=$(echo -E "$asset_json_raw" | jq -r ".[\"url\"] = .direct_asset_url")
asset_json=$(echo -E "$asset_json_raw" | jq -c ". += {createdAt: \"$timestamp\"}")
else
asset_json=$(gh release view "$latest_release" --json assets -q ".[] | .[$i]" -R ${{ matrix.components.repo }})
fi
echo "asset=$asset_json" >> $GITHUB_OUTPUT
echo "version=${latest_release#${{ matrix.components.version-prefix }}}" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
repository: bottlesdevs/tools
path: "tools"
- name: Define environment variables
run: |
lowercase_component_name=$(echo "${{ matrix.components.name-prefix }}${{ steps.check-release.outputs.version }}${{ matrix.components.name-suffix }}" | tr "[:upper:]" "[:lower:]")
name_prefix="$(echo ${{ matrix.components.name-prefix }} | tr '[:upper:]' '[:lower:]')"
echo "NAMEPREFIX=$name_prefix" >> $GITHUB_ENV
echo "NAMESUFFIX=$(echo ${{ matrix.components.name-suffix }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
echo "NAME=$lowercase_component_name" >> $GITHUB_ENV
echo "CATEGORY=${{ matrix.components.Category }}" >> $GITHUB_ENV
echo "SUBCATEGORY=${{ matrix.components.Sub-category }}" >> $GITHUB_ENV
echo "CHANNEL=stable" >> $GITHUB_ENV
echo "YAML_FILENAME=${{ matrix.components.yaml-file }}" >> $GITHUB_ENV
echo "CREATED_AT=${{ fromJSON(steps.check-release.outputs.asset).createdAt }}" >> $GITHUB_ENV
echo "UPDATED=false" >> $GITHUB_ENV
# Components specific tweaks
if [[ "${{ matrix.components.repo }}" == "GloriousEggroll/wine-ge-custom" ]]; then
url="${{ fromJSON(steps.check-release.outputs.asset).url }}"
name="${url##*/wine-}"
name="${name%.tar*}"
name="${name%-x86_64}"
if [[ "$name" == "lutris-ge-lol-"* ]]; then
echo "NAMEPREFIX=lutris-ge-lol-" >> $GITHUB_ENV
echo "NAME=$name" >> $GITHUB_ENV
fi
elif [[ "${{ matrix.components.repo }}" == "Kron4ek/Wine-Builds" ]]; then
echo "NAMEPREFIX=kron4ek-$name_prefix" >> $GITHUB_ENV
echo "NAME=kron4ek-$lowercase_component_name" >> $GITHUB_ENV
fi
- name: Update stable input_file entry
working-directory: "bottle-components-repository"
run: |
# This script can set env.UPDATED to true
./input_files/update_yml_entries.sh
- name: Create release tar archive
if: env.UPDATED == 'true'
working-directory: "bottle-components-repository"
run: |
release_archive_url=${{ fromJSON(steps.check-release.outputs.asset).url }}
release_archive_name=${{ fromJSON(steps.check-release.outputs.asset).name }}
if [[ $release_archive_name == *".tar.zst" ]]; then
curl -fsSLO "$release_archive_url"
tar --use-compress-program=unzstd -xvf $release_archive_name
tar -zcvf "${{ env.NAME }}.tar.gz" "${{ env.NAME }}"
echo "UPLOAD_FILE=$(pwd)/${{ env.NAME }}.tar.gz" >> $GITHUB_ENV
elif [[ $release_archive_name == "dxvk-nvapi"* ]]; then
curl -fsSLO "$release_archive_url"
mkdir "${{ env.NAME }}"
tar -xvf $release_archive_name --directory "${{ env.NAME }}"
tar -zcvf "${{ env.NAME }}.tar.gz" "${{ env.NAME }}"
echo "UPLOAD_FILE=$(pwd)/${{ env.NAME }}.tar.gz" >> $GITHUB_ENV
fi
- name: Check for new artifact
id: download-artifact
if: matrix.components.workflow != '' && env.UPDATED != 'true'
shell: bash {0}
run: |
run_id=$(gh run list -b ${{ matrix.components.branch }} -w ${{ matrix.components.workflow }} -R ${{ matrix.components.repo }} --json databaseId -q '.[] | .databaseId' --status success -L 1)
status=$?
if [ $status -ne 0 ]; then
echo "::error::Could not get run ID of last successful run."
exit 1
fi
found_artifact=true
gh run download -R ${{ matrix.components.repo }} $run_id -D artifact
status=$?
if [ $status -ne 0 ]; then
echo "::warning::Could not download artifact, probably expired."
found_artifact=false
else
artifact_info=$(gh run view -R ${{ matrix.components.repo }} $run_id --json headSha,createdAt -q '.')
echo "artifact_info=$artifact_info" >> $GITHUB_OUTPUT
fi
echo "found_artifact=$found_artifact" >> $GITHUB_OUTPUT
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update environment variables
if: env.UPDATED != 'true' && steps.download-artifact.outputs.found_artifact == 'true'
run: |
commit_sha1="${{ fromJSON(steps.download-artifact.outputs.artifact_info).headSha }}"
echo "NAME=${{ env.NAME }}-1-${commit_sha1::7}" >> $GITHUB_ENV
echo "CHANNEL=unstable" >> $GITHUB_ENV
echo "CREATED_AT=${{ fromJSON(steps.download-artifact.outputs.artifact_info).createdAt }}" >> $GITHUB_ENV
- name: Update unstable input_file entry
if: env.UPDATED != 'true' && steps.download-artifact.outputs.found_artifact == 'true'
working-directory: "bottle-components-repository"
run: |
# This script can set env.UPDATED to true
./input_files/update_yml_entries.sh
- name: Create artifact tar archive
if: env.UPDATED == 'true' && steps.download-artifact.outputs.found_artifact == 'true'
working-directory: "bottle-components-repository"
run: |
folder=$(find "${{ github.workspace }}/artifact" -name "${{ env.NAMEPREFIX }}*")
# Components specific tweaks
if [[ "${{ env.NAMEPREFIX }}" == "dxvk"* ]]; then
rm -rf "$folder/usr"
fi
mkdir "${{ env.NAME }}"
mv "$folder"/* "${{ env.NAME }}"
tar -zcvf "${{ env.NAME }}.tar.gz" "${{ env.NAME }}"
echo "UPLOAD_FILE=$(pwd)/${{ env.NAME }}.tar.gz" >> $GITHUB_ENV
- name: Upload component archive
id: upload-component
if: env.UPLOAD_FILE != ''
working-directory: "bottle-components-repository"
shell: bash {0}
run: |
gh release create "${{ env.NAME }}" ${{ env.UPLOAD_FILE }} -n ""
status=$?
if [ $status -ne 0 ]; then
gh release upload "${{ env.NAME }}" ${{ env.UPLOAD_FILE }} --clobber
status=$?
if [ $status -ne 0 ]; then
echo "::error::Could not upload component."
fi
fi
asset=$(gh release view "${{ env.NAME }}" --json assets -q ".[] | .[0]")
echo "asset=$asset" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name : Generate appropriate YAML file
if: env.UPDATED == 'true'
working-directory: "bottle-components-repository"
run: |
repo=${{ matrix.components.repo }}
name=${{ env.NAME }}
if [ "${{ env.UPLOAD_FILE }}" != "" ]; then
url="${{ steps.upload-component.outputs.asset && fromJSON(steps.upload-component.outputs.asset).url }}"
path="${{ env.UPLOAD_FILE }}"
else
url="${{ fromJSON(steps.check-release.outputs.asset).url }}"
fi
python "${{ github.workspace }}/tools/MaintainersHelpers/component-generator.py" "components" "CI" "$name" "${repo%/*}" "${{ env.CHANNEL }}" "$url" $path
# Components specific tweaks
if [[ "$repo" == "GloriousEggroll"* ]]; then
source="${url##*/}"
source="${source#wine-}"
source="${source%.tar*}"
source="${source%-x86_64}"
echo "Post:" >> "$name.yml"
echo -e "- action: rename" >> "$name.yml"
echo -e " source: $source" >> "$name.yml"
echo -e " dest: $name" >> "$name.yml"
elif [[ "$repo" == "Kron4ek/Wine-Builds" ]]; then
echo "Post:" >> "$name.yml"
echo -e "- action: rename" >> "$name.yml"
echo -e " source: ${name#kron4ek-}" >> "$name.yml"
echo -e " dest: $name" >> "$name.yml"
fi
mv "$name.yml" "${{ env.CATEGORY }}/${{ env.SUBCATEGORY }}"
- name : Commit changes
if: env.UPDATED == 'true'
working-directory: "bottle-components-repository"
timeout-minutes: 10
shell: bash {0}
run: |
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add "${{ env.CATEGORY }}/${{ env.SUBCATEGORY }}/${{ env.NAME }}.yml" "input_files/${{ env.YAML_FILENAME }}"
git commit -m "Add ${{ env.NAME }}"
file_name="$(date -d "${{ github.event.created_at }}" +%s)-${{ matrix.components.order }}-${{ env.NAME }}.patch"
git diff HEAD~1 HEAD > "$file_name"
git fetch origin ${{ env.WORKING_BRANCH }}:${{ env.WORKING_BRANCH }}
git switch ${{ env.WORKING_BRANCH }}
git branch --set-upstream-to=origin/${{ env.WORKING_BRANCH }} ${{ env.WORKING_BRANCH }}
mv "$file_name" patch_dir
git add patch_dir/*.patch
git pull
git commit -m "Add ${{ env.NAME }}"
git push
success=$?
until [ $success -eq 0 ]; do
git pull --rebase;
git push
success=$?
done
finish:
needs: [prepare, pull]
if: always() && needs.prepare.result == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: "bottle-components-repository"
ref: ${{ env.WORKING_BRANCH }}
fetch-depth: 0
- name: Generate index.yml
working-directory: "bottle-components-repository"
shell: bash {0}
run: |
git checkout ${{ github.ref_name }}
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git merge ${{ env.WORKING_BRANCH }} --no-commit --no-ff
git reset
readarray -d '' entries < <(printf '%s\0' patch_dir/*.patch | sort -zV)
for entry in "${entries[@]}"; do
patch -p1 --fuzz 5 < "$entry"
git add -- . ':!patch_dir' ':!**.orig'
entry=${entry#patch_dir/*-[0-9]*-}
git commit -a -m "Add component ${entry%\.patch}"
done
./generate_index.sh
git add index.yml
git commit -m "Generate index.yml" || true
- name: Create Pull Request
id: cpr
working-directory: "bottle-components-repository"
shell: bash {0}
run: |
git checkout -B ${{ env.PR_BRANCH }}
git push -f --set-upstream origin ${{ env.PR_BRANCH }}
gh_output=$(gh pr create --title "Update available :tada:" --body "One or more components have been updated!" --head ${{ env.PR_BRANCH }} --base ${{ github.ref_name }})
echo "PR_CREATED=$([ $? -eq 0 ] && echo true || echo false)" >> $GITHUB_OUTPUT
pr_number=$($gh_output | tail -n1)
echo "PR_NUMBER=${pr_number#https://github.com/${{ github.repository }}/pull/}" >> $GITHUB_OUTPUT
env:
# PAT is not necessary unless auto-merge is used
# GH_TOKEN: ${{secrets.PAT}}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Pull Request Automerge
if: false
# if: steps.cpr.outputs.PR_CREATED == 'true'
run: gh pr merge --merge --auto "${{ steps.cpr.outputs.PR_NUMBER }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Auto approve
if: false
# if: steps.cpr.outputs.PR_CREATED == 'true'
run: gh pr review --approve "${{ steps.cpr.outputs.PR_NUMBER }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}