name: Flatpak release job on: workflow_call: inputs: ryujinx_version: required: true type: string concurrency: flatpak-release jobs: release: timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }} runs-on: ubuntu-latest env: NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages GIT_COMMITTER_NAME: "RyujinxBot" GIT_COMMITTER_EMAIL: "61127645+RyujinxBot@users.noreply.github.com" RYUJINX_PROJECT_FILE: "src/Ryujinx/Ryujinx.csproj" NUGET_SOURCES_DESTDIR: "nuget-sources" RYUJINX_VERSION: "${{ inputs.ryujinx_version }}" steps: - uses: actions/checkout@v4 with: path: Ryujinx - uses: actions/setup-dotnet@v4 with: global-json-file: Ryujinx/global.json - name: Get version info id: version_info working-directory: Ryujinx run: | echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - uses: actions/checkout@v4 with: repository: flathub/org.ryujinx.Ryujinx token: ${{ secrets.RYUJINX_BOT_PAT }} submodules: recursive path: flathub - name: Install dependencies run: python -m pip install PyYAML lxml - name: Restore Nuget packages # With .NET 8.0.100, Microsoft.NET.ILLink.Tasks isn't restored by default and only seems to appear when publishing. # So we just publish to grab the dependencies run: | dotnet publish -c Release -r linux-x64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained dotnet publish -c Release -r linux-arm64 Ryujinx/${{ env.RYUJINX_PROJECT_FILE }} --self-contained - name: Generate nuget_sources.json shell: python run: | import hashlib from pathlib import Path import base64 import binascii import json import os import urllib.request sources = [] def create_source_from_external(name, version): full_dir_path = Path(os.environ["NUGET_PACKAGES"]).joinpath(name).joinpath(version) os.makedirs(full_dir_path, exist_ok=True) filename = "{}.{}.nupkg".format(name, version) url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format( name, version, filename ) print(f"Processing {url}...") response = urllib.request.urlopen(url) sha512 = hashlib.sha512(response.read()).hexdigest() return { "type": "file", "url": url, "sha512": sha512, "dest": os.environ["NUGET_SOURCES_DESTDIR"], "dest-filename": filename, } has_added_x64_apphost = False for path in Path(os.environ["NUGET_PACKAGES"]).glob("**/*.nupkg.sha512"): name = path.parent.parent.name version = path.parent.name filename = "{}.{}.nupkg".format(name, version) url = "https://api.nuget.org/v3-flatcontainer/{}/{}/{}".format( name, version, filename ) with path.open() as fp: sha512 = binascii.hexlify(base64.b64decode(fp.read())).decode("ascii") sources.append( { "type": "file", "url": url, "sha512": sha512, "dest": os.environ["NUGET_SOURCES_DESTDIR"], "dest-filename": filename, } ) # .NET will not add current installed application host to the list, force inject it here. if not has_added_x64_apphost and name.startswith('microsoft.netcore.app.host'): sources.append(create_source_from_external("microsoft.netcore.app.host.linux-x64", version)) has_added_x64_apphost = True with open("flathub/nuget_sources.json", "w") as fp: json.dump(sources, fp, indent=4) - name: Update flatpak metadata id: metadata env: RYUJINX_GIT_HASH: ${{ steps.version_info.outputs.git_hash }} shell: python run: | import hashlib import hmac import json import os import yaml from datetime import datetime from lxml import etree # Ensure we don't destroy multiline strings def str_presenter(dumper, data): if len(data.splitlines()) > 1: return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") return dumper.represent_scalar("tag:yaml.org,2002:str", data) yaml.representer.SafeRepresenter.add_representer(str, str_presenter) yaml_file = "flathub/org.ryujinx.Ryujinx.yml" xml_file = "flathub/org.ryujinx.Ryujinx.appdata.xml" with open(yaml_file, "r") as f: data = yaml.safe_load(f) for source in data["modules"][0]["sources"]: if type(source) is str: continue if ( source["type"] == "git" and source["url"] == "https://github.com/Ryujinx/Ryujinx.git" ): source["commit"] = os.environ['RYUJINX_GIT_HASH'] is_same_version = data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] == os.environ['RYUJINX_VERSION'] with open(os.environ['GITHUB_OUTPUT'], "a") as gh_out: if is_same_version: gh_out.write(f"commit_message=Retry update to {os.environ['RYUJINX_VERSION']}") else: gh_out.write(f"commit_message=Update to {os.environ['RYUJINX_VERSION']}") if not is_same_version: data["modules"][0]["build-options"]["env"]["RYUJINX_VERSION"] = os.environ['RYUJINX_VERSION'] with open(yaml_file, "w") as f: yaml.safe_dump(data, f, sort_keys=False) parser = etree.XMLParser(remove_blank_text=True) tree = etree.parse(xml_file, parser) root = tree.getroot() releases = root.find("releases") element = etree.Element("release") element.set("version", os.environ['RYUJINX_VERSION']) element.set("date", datetime.now().date().isoformat()) releases.insert(0, element) # Ensure 4 spaces etree.indent(root, space=" ") with open(xml_file, "wb") as f: f.write( etree.tostring( tree, pretty_print=True, encoding="UTF-8", doctype='', ) ) - name: Push flatpak update working-directory: flathub env: COMMIT_MESSAGE: ${{ steps.metadata.outputs.commit_message }} run: | git config user.name "${{ env.GIT_COMMITTER_NAME }}" git config user.email "${{ env.GIT_COMMITTER_EMAIL }}" git add . git commit -m "$COMMIT_MESSAGE" git push origin master