Skip to content

Repository that contains workflows for building multiple variants of SKSE mods that use CMake

License

Notifications You must be signed in to change notification settings

adya/pack-skse-mod

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Pack SKSE Mod

A universal workflow to build SKSE mods that are based on powerof3/CommonLibSSE and/or alandtse/CommonLibVR.

Features

  • ✅ Effortless - doesn't require specific GitHub Actions knowledge, easy to setup.
  • ✅ Builds all supported variants: SE, AE, AE (1.6.353), VR.
  • ✅ Include PDB files along with DLLs for easier debugging.
  • ✅ Generates FOMOD.
  • ✅ Publishes FOMOD installer to GitHub Releases.
  • Publishes FOMOD installer directly to Nexus mod page (Coming soon-ish).

Contents

Setting up the workflow

The workflow tries to be as unintrusive to the actual build process as possible and has only few requirements:

  1. Add powerof3/CommonLibSSE and/or alandtse/CommonLibVR as git submodules:
git submodule add extern/CommonLibSSE https://github.com/powerof3/CommonLibSSE.git
git submodule add extern/CommonLibVR https://github.com/alandtse/CommonLibVR.git

Note: Make sure to point CMake to submodules paths in CMakeLists.txt.

  1. Set NAME and VERSION variables as cache variables in CMakeLists.txt. (See Binary Name and Version for other options):
set(NAME "my_skse_mod" CACHE STRING "")
set(VERSION 1.0.0 CACHE STRING "")
  1. Add a workflow file at the repository's root .github/workflows/main.yml:
name: Main

on:
  push:
    branches: '**'
    tags: '*'

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_MOD_NAME: "My SKSE Mod"
      FOMOD_MOD_AUTHOR: "The Author"

Note: Default values for configuration of pack.yml workflow is based on powerof3 projects. This includes preset names, build directories, variable names, etc. If your project uses different naming you need to also specify custom values as described below.


Examples

Here are some examples of configured workflows:

  • AnimObjectSwapper: Basic configuration, builds SE, AE, VR, packs installer into 7z with PDB files.
  • EnhancedReanimation: Does everything that AnimObjectSwapper + supports AE 1.6.353 as a separate variant.
  • Spell Perk Item Distributor: Showcases custom project path, configuration of the FOMOD, provides image and links to changelog and description files.

SSH

If your repository or one of it's submodules uses an SSH, you may specify an SSH key that workflow will use to checkout such repositories.

Note: You should provide your SSH key as a Secret.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    secrets:
      GIT_SSH_KEY: ${{ secrets.MY_SSH_KEY }}

CMake Configuration

CMake Presets

The workflow supports both Configuration Presets and Build Presets.

By default it is configured as the following:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_SE_CONFIG_PRESET: 'vs2022-windows-vcpkg-se'
      CMAKE_SE_BUILD_PRESET: ''
      CMAKE_AE_CONFIG_PRESET: 'vs2022-windows-vcpkg-ae'
      CMAKE_AE_BUILD_PRESET: ''
      CMAKE_VR_CONFIG_PRESET: 'vs2022-windows-vcpkg-vr'
      CMAKE_VR_BUILD_PRESET: ''

Note: Build Presets are an opt-in feature, if these presets are not specified then the workflow will perform cmake --build $BINARY_DIR --config Release. If your CMakePresets.json provide build presets you can set them via these parameters and the workflow will do cmake --build --preset $BUILD_PRESET instead.

The workflow checks whether specified Configuration Presets are present in CMakePresets.json and builds only variants that have existing presets. You might explicitly disable building of any variant by passing blank string to corresponding Configuration Preset.


Build Configurations

By default workflow assumes that Release build configuration will be used to build the project. This configuration is also used to determine path to the build artifacts that will be packed into FOMOD. When you want to use build configurations other than Release you can specify it with a CMAKE_BUILD_CONFIGURATION variable. For example, if you want to create both Release and Debug variants of the mod you can do this in your main.yaml:

jobs:
  release:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_BUILD_CONFIGURATION: 'Release'
      FOMOD_MOD_NAME: "My SKSE Mod"
      FOMOD_MOD_AUTHOR: "The Author"
      
  debug:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_BUILD_CONFIGURATION: 'Debug'
      FOMOD_MOD_NAME: "My SKSE Mod DEBUG"
      FOMOD_MOD_AUTHOR: "The Author"

This will produce two FOMOD installers with corresponding artifacts.


Binary Directory

A directory where CMake outputs build files. By default the workfow sets binary directories for variants as follows:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_SE_BINARY_DIR: 'build'
      CMAKE_AE_BINARY_DIR: 'buildae'
      CMAKE_VR_BINARY_DIR: 'buildvr'

If you have different binary directories you should provide them via these parameters.


Project Root

When plugin's project files do not reside directly in the repository's root you should specify a path to it using CMAKE_PROJECT_DIR. This will point vcpkg to %repository_root%/CMAKE_PROJECT_DIR/vcpkg.json and append CMAKE_PROJECT_DIR as a suffix to CMAKE_XX_BINARY_DIR variables, so that build products will be searched for in %repository_root%/CMAKE_XX_BINARY_DIR/CMAKE_PROJECT_DIR/Release/:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_PROJECT_DIR: ""

For example, SPID plugin's project files are located at ./SPID, so it uses CMAKE_PROJECT_DIR: "SPID"


Binary Name and Version

The workflow retrives information such as built product's name and version using CMake's cache. It is used to later generate FOMOD and publish the mod. By default it looks for common variables NAME and VERSION.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_BINARY_NAME_VAR: "NAME"
      CMAKE_BINARY_VERSION_VAR: "VERSION"

You may provide any other cached variable to be used as NAME or VERSION respectfully.

Note: It is important that these variables are defined as CACHE variables, otherwise workflow will fail to read them.

You might also explicilty specify values for NAME and VERSION if you don't want to make CMake variables cached.

Though, you'll need to update these values (at least VERSION) in your workflow every time you change the version.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      CMAKE_BINARY_NAME: "my_skse_mod"
      CMAKE_BINARY_VERSION: "1.0.0"

Building AE 1.6.353 (pre 1.6.629 variant)

This is another opt-in feature. It is disabled by default.

Support for AE 1.6.353 is implemented through checkouting a dedicated branch that is built against powerof3/CommonLibSSE's dev-1.6.353 branch.

You can opt-in by providing such branch like this:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      AE_353_BRANCH: "ae_353_branch" # name of the branch that can be built with dev-1.6.353

If you don't have a separate branch for 1.6.353 and your main branch supports all AE versions, then you can specify workflow's current branch to enable this feature:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      AE_353_BRANCH: "${{ github.ref }}"

Note: You can also change CommonLibSSE's branch to be used for 1.6.353 build by specifying it with AE_353_COMMON_LIB_BRANCH parameter.

Note: This variant uses AE-related build parameters of the workflow.


FOMOD Customizations

The ultimate artifact produced by this workflow is a FOMOD installer containing all built variants that is ready to be published to Nexus or any other platform.

The FOMOD has built-in automated detection of appropriate game version and pre-selects correct option for user.

General Information

The metadata that is provided in info.xml:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_MOD_NAME: "My SKSE Mod"
      FOMOD_MOD_AUTHOR: "The Author"

Note: Version is picked up from binary's version, so there is no dedicated FOMOD_MOD_VERSION.


Nexus Mods Integration

Optionally you can specify id of your mod on Nexus page. It will be used to provide a URL to your mod in FOMOD.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_MOD_NEXUS_ID: "1111"

Installation Paths

Source Paths

Source paths are paths that specify where installable files are located within FOMOD. These paths are relative to the installer's root.

By default, workflow is preconfigured for a common installer template with the following structure:

installer
├───Required*
├───SE
│   └───SKSE
│       └───Plugins
├───AE353
│   └───SKSE
│       └───Plugins
├───AE
│   └───SKSE
│       └───Plugins
└───VR
    └───SKSE
        └───Plugins

This corresponds to the following configuration, that you may choose to customize:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_VR_PATH: "VR/SKSE/Plugins"
      FOMOD_SE_PATH: "SE/SKSE/Plugins"
      FOMOD_AE_PATH: "AE/SKSE/Plugins"
      FOMOD_AE353_PATH: "AE353/SKSE/Plugins"

Note: * 'Required' is an optional path and configured with FOMOD_REQUIRED_SRC_PATH. (See Additional required installation


Destination Paths

Destinations paths are paths that specify where files should be installed to. ****.

Note: These paths are relative to game's Data/ folder, so you should not start destination paths with "Data/" as this might cause issues in some mod managers. For instance, Vortex handles such paths correctly, but MO2 does not.

Installation path for all options is configured with FOMOD_DST_PATH and by default is set to SKSE/Plugins.


Additional Required Installation

You also may have additional files you'd want to include along with plugin variants. For this case you can specify a directory containing files that you want to be always installed using FOMOD_REQUIRED_INSTALLATION_DIR parameter. This path is relative to your repository's root where you place the required files. The files in specified directory will be copied into FOMOD's installer to directory specified with in FOMOD_REQUIRED_SRC_PATH.

By default, FOMOD_REQUIRED_INSTALLATION_DIR is blank, so that required installation is skipped.

Aditionally, you may customize where required files will be placed inside FOMOD and the default installation path within Game's folder.

Here is an example of all relevant inputs:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_REQUIRED_INSTALLATION_DIR: "FOMOD/Required Files"
      FOMOD_REQUIRED_SRC_PATH: "Required"

Note that contents of FOMOD_REQUIRED_INSTALLATION_DIR will be copied to game's Data folder (this is the default FOMOD_REQUIRED_DST_PATH).


Including Program Debug Database (PDB) files

If you'd like to distribute your mod with PDB files, you may specify FOMOD_INCLUDE_PDB option. This will include PDB files into FOMOD and install them along with DLLs.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_INCLUDE_PDB: true

Installer Content

Things like installer's title, option names, descriptions, minimum required game versions are all configurable using the following parameters:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_TITLE: 'Main'
      FOMOD_GROUP_NAME: 'DLL'
      FOMOD_SE_NAME: 'SSE v1.5.97 ("Special Edition")'
      FOMOD_SE_DESCR: 'Select this if you are using Skyrim Special Edition v1.5.97.'
      FOMOD_SE_MIN_GAME_VERSION: '1.5.97.0'
      FOMOD_AE353_NAME:  'SSE v1.6.353 ("Anniversary Edition")'
      FOMOD_AE353_DESCR: 'Select this if you are using Skyrim Anniversary Edition v1.6.353 or lower.'
      FOMOD_AE353_MIN_GAME_VERSION: '1.6.317.0'
      FOMOD_AE_NAME: 'SSE v1.6.629+ ("Anniversary Edition")'
      FOMOD_AE_DESCR: 'Select this if you are using Skyrim Anniversary Edition v1.6.629 or higher (latest update).'
      FOMOD_AE_MIN_GAME_VERSION: '1.6.629.0'
      FOMOD_VR_NAME: 'VR v1.4.15 ("Skyrim VR")'
      FOMOD_VR_DESCR: 'Select this if you are using Skyrim VR v1.4.15.'
      FOMOD_VR_MIN_GAME_VERSION: '1.4.15.0'

Installation Option Images

In addition to textual content of the installer you might as well provide cover images for each installation option. Put them inside your repository and specify paths to these images. Path is relative to repository's root.

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_SE_IMAGE: 'FOMOD/images/cover_se.png'
      FOMOD_AE353_IMAGE: 'FOMOD/images/cover_ae353.png'
      FOMOD_AE_IMAGE: 'FOMOD/images/cover_ae.png'
      FOMOD_VR_IMAGE: 'FOMOD/images/cover_vr.png'

Note that images are copied to dedicated FOMOD's folder (fomod/images), so make sure your images have distrinct names, otherwise they'll be overwritten by one another.

Default image for all options

If you don't have separate images for each variant (or only for few of them) you might instead provide FOMOD_DEFAULT_IMAGE which will be used when variant's image is not provided.

For example here all variants except VR will use default 'cover.png', but VR will have it's own image:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_DEFAULT_IMAGE: 'FOMOD/images/cover.png'
      FOMOD_VR_IMAGE: 'FOMOD/images/cover_vr.png'

Publishing

When you push a new tag to GitHub, the workflow will perform an additional publishing step.

Even though the workflow doesn't use tag's name as a version, you should still follow Semantic Versioning for the sake of clarity :)


Archive Type

When publishing FOMOD installer you may specify what archiver to use. Currently supported are zip and 7z:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      PUBLISH_ARCHIVE_TYPE: '7z'

Note: By deafult workflow will use PUBLISH_ARCHIVE_TYPE: 'zip'.

Note: This option is only relevant for publishing, since Artifacts produced by separate jobs are packed into zip automatically by GitHub Actions.


GitHub Releases

One of the destinations where package can be published is GitHub's Releases. Once workflow publishes there you'll be able to download the installer's archive from Releases page of your repository.

You may also specify changelog and description of the mod file. They'll be added to that Release:

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      PUBLISH_MOD_DESCRIPTION_FILE: 'FOMOD/description.txt'
      PUBLISH_MOD_CHANGELOG_FILE: 'FOMOD/changelog.txt'

Nexus Mod

This one is work in progress and is not included in @main. It's also highliy experimental :) so if you feel adventurous you might try it on @nexus-upload

DISCLAIMER: As of now there is no official NexusMods API to upload files, this step uses known, yet still unofficial tool to perform upload.

This will publish produced installer's package directly to your mod's Nexus page, replacing the Main file that had the latest version. So if your mod had several published Main files the first one with largest version will be update.

VERSION variable from you CMakeLists.txt will be used as a new version of the uploaded file.

To configuration the workflow you'll need to do the following:
  1. If you don't have Nexus's Personal API Key, then Create one.
  2. Add this key to your repositor's secrets. Refer to GitHub Secrets docs. 1.1. or if you plan on using it in multiple repositories, consider creating your own organization and moving all repos there, so they'll share the same Organization's secrets.
  3. Get Cookies from your active Nexus session. This can be done in various ways, for example, using *Get cookies.txt for Google Chrom (or Microsoft Edge)
  4. Once set you're ready to enable publishing on Nexus step:
jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_MOD_NEXUS_ID: '11111'
      PUBLISH_GAME_NAME: 'skyrimspecialedition'
      PUBLISH_MOD_DESCRIPTION_FILE: 'FOMOD/description.txt'
      PUBLISH_MOD_CHANGELOG_FILE: 'FOMOD/changelog.txt'
    secrets:
      PUBLISH_NEXUS_API_KEY: ${{ secrets.YOUR_NEXUS_API_KEY_SECRET }}
      PUBLISH_NEXUS_COOKIE: ${{ secrets.YOUR_NEXUS_COOKIES_SECRET }}

Replace YOUR_NEXUS_API_KEY_SECRET and YOUR_NEXUS_COOKIES_SECRET with corresponding secrets that you've created.

IMPORTANT: You must also provide FOMOD_MOD_NEXUS_ID as it will be used for publishing.

Extending The Workflow

The workflow exposes all useful data as outputs. This allows building your custom workflows on top of pack-skse-mod.

Here are currently available outputs:

  • PRODUCT_VERSION
  • FOMOD_INSTALLER
  • SE_ARTIFACT_NAME
  • AE_ARTIFACT_NAME
  • AE353_ARTIFACT_NAME
  • VR_ARTIFACT_NAME

which can be used in your workflow like this:

name: Main

on:
  push:
    branches: '**'
    tags: '*'

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

jobs:
  run:
    uses: adya/pack-skse-mod/.github/workflows/pack.yml@main
    with:
      FOMOD_MOD_NAME: "My SKSE Mod"
      FOMOD_MOD_AUTHOR: "The Author"

  post-discord-notification:
    runs-on: windows-latest
    needs: run
    steps:
      - name: Print version
        run: echo "Built Version ${{needs.run.outputs.PRODUCT_VERSION}}"

About

Repository that contains workflows for building multiple variants of SKSE mods that use CMake

Resources

License

Stars

Watchers

Forks