Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/maint-cleanup-releases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ jobs:
# Get all git tags that look like pre-releases but may not have GitHub releases
git fetch --tags
orphaned_tags=$(git tag -l | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+-(pr[0-9]+|rc[0-9]+|alpha[0-9]*|beta[0-9]*|dev[0-9]*)' || true)
# Optional '.' before the number so semantic-release's dotted
# prerelease tags (e.g. v1.6.0-rc.1) are matched, not just
# v1.6.0-rc1.
orphaned_tags=$(git tag -l | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+-(pr|rc|alpha|beta|dev)\.?[0-9]+' || true)
# Combine both lists and remove duplicates
all_prerelease_tags=$(echo -e "$releases\n$orphaned_tags" | sort | uniq | grep -v '^$' || true)
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/nexus-upload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,19 @@ jobs:
fi
echo "file=$FILE" >> $GITHUB_OUTPUT
LINK="https://github.com/${REPO}/releases/tag/${RELEASE_TAG}"
if [ -n "$FILE_DESC" ]; then
printf 'description=%s Full changelog: %s\n' "$FILE_DESC" "$LINK" >> $GITHUB_OUTPUT
else
printf 'description=Full changelog: %s\n' "$LINK" >> $GITHUB_OUTPUT
fi
# file_description is multi-line (per-feature compatibility
# bullets), so write it with the heredoc-delimiter form. A plain
# 'description=...' breaks $GITHUB_OUTPUT on the embedded newlines
# ("Error: Invalid format '• HDR 1.0.2'").
{
echo 'description<<NEXUS_DESC_EOF'
if [ -n "$FILE_DESC" ]; then
printf '%s Full changelog: %s\n' "$FILE_DESC" "$LINK"
else
printf 'Full changelog: %s\n' "$LINK"
fi
echo 'NEXUS_DESC_EOF'
} >> "$GITHUB_OUTPUT"

- name: Validate file_group_id
if: steps.version-check.outputs.should_upload == 'true'
Expand Down
18 changes: 10 additions & 8 deletions .github/workflows/release-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ concurrency:
jobs:
build:
name: Build
# Build on dispatch / tag push / a non-draft `release: created`, but NOT
# on `release: published`: the artifacts were already built and attached
# when the draft was created, so publishing must not rebuild.
if: github.event.action != 'published'
uses: ./.github/workflows/_shared-build.yaml
with:
ref: ${{ github.ref }}
Expand All @@ -46,7 +50,7 @@ jobs:

feature-audit:
name: Feature Version Audit (Release)
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'release'
if: (startsWith(github.ref, 'refs/tags/v') || github.event_name == 'release') && github.event.action != 'published'
runs-on: ubuntu-latest
continue-on-error: true
steps:
Expand Down Expand Up @@ -78,6 +82,7 @@ jobs:
if: >
always() && !cancelled() &&
needs.build.outputs.cpp-built == 'true' &&
github.event.action != 'published' &&
(github.event_name == 'workflow_dispatch' ||
startsWith(github.ref, 'refs/tags/v') ||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')))
Expand Down Expand Up @@ -187,16 +192,13 @@ jobs:
allowUpdates: true

nexus-dry-run:
# Chained from `release` to avoid the artifact-attachment race a
# parallel `release: published` trigger on a separate workflow had:
# the prior release-nexus-trigger.yaml fired in parallel with this
# build and tried to download artifacts before they existed.
# Runs only on publish, independently of the build jobs (which are
# skipped on publish). Artifacts were already built and attached to the
# release when its draft was created, and nexus-upload downloads them
# from the release assets — so there is nothing to wait on and no rebuild.
# Stable tags only (no '-' in the tag name).
name: Nexus Upload (dry run)
needs: [release]
if: >
always() && !cancelled() &&
needs.release.result == 'success' &&
github.event_name == 'release' &&
github.event.action == 'published' &&
!contains(github.event.release.tag_name, '-')
Expand Down
11 changes: 3 additions & 8 deletions .github/workflows/release-hotfix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,9 @@ jobs:
- name: Open PR against hotfix branch
if: ${{ !inputs.dry_run && steps.cherry.outputs.picked_count != '0' }}
env:
# Use GITHUB_TOKEN (not RELEASE_PAT). The workflow declares
# `permissions: pull-requests: write`, which is sufficient
# for creating the candidate PR — no branch-protection
# bypass is required here, so there's no need to spend
# RELEASE_PAT's broader scope (and avoids depending on the
# PAT having pull_requests:write granted, which a previous
# run hit: "Resource not accessible by personal access
# token (createPullRequest)").
# GITHUB_TOKEN suffices here: the workflow declares
# `permissions: pull-requests: write`, and creating the
# candidate PR requires no branch-protection bypass.
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Pass via env (not ${{ }} interpolation) so the literal
# backticks inside SOURCE_DESC don't get re-evaluated by
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/release-semantic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ on:

permissions:
contents: write
# actions:write lets this job dispatch release-build.yaml after cutting a
# release (the tag push can't trigger it — see the step below).
actions: write

concurrency:
# Serialize promotions so two concurrent dispatches on main can't race
Expand Down Expand Up @@ -173,6 +176,24 @@ jobs:
# (release-build.yaml); GITHUB_TOKEN pushes do not.
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Build artifacts for the new release
# The release tag does NOT auto-trigger release-build.yaml: it sits
# on a `chore(release): … [skip ci]` commit (the tag push is skipped)
# and the GitHub release is created as a draft (no `release: created`
# event fires). So dispatch the build explicitly here to populate the
# draft with .7z artifacts. Publishing the draft later does NOT
# rebuild — release-build.yaml skips its build job on the
# `release: published` event — it just publishes the already-attached
# artifacts and fires the Nexus dry-run via `release: published`.
if: steps.semantic.outputs.new_release_published == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.semantic.outputs.new_release_git_tag }}
run: |
gh workflow run release-build.yaml \
--repo "${{ github.repository }}" \
--ref "${TAG}"

- name: Reconcile dev with release commit (promotion mode, dev source only)
if: ${{ inputs.ff_target != '' && steps.semantic.outputs.new_release_published == 'true' && steps.validate.outputs.source == 'dev' }}
env:
Expand Down
3 changes: 2 additions & 1 deletion features/Terrain Helper/Shaders/Features/TerrainHelper.ini
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
[Info]
Version = 1-0-1
AuditVersion = false

[Nexus]
nexusmodid = 143149
nexusfilegroupid = 000000
nexusfilename = Terrain Helper
autoupload = true
autoupload = false
17 changes: 16 additions & 1 deletion tools/feature_version_audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def get_feature_ini_metadata(feature_dir_or_ini_path):
if not sections:
sections = ['Info'] if parser.has_section('Info') else []

metadata = {'auto_upload': False}
metadata = {'auto_upload': False, 'audit_version': True}
for section in sections:
if not parser.has_section(section):
continue
Expand All @@ -196,6 +196,15 @@ def get_feature_ini_metadata(feature_dir_or_ini_path):
if auto_upload_str is not None:
metadata['auto_upload'] = str(auto_upload_str).strip().lower() not in ('false', '0', 'no', 'off', '')

# Activation-only features keep all code in the core mod; their toggle
# .ini opts out of version auditing/bumping with `AuditVersion = false`.
# Auditing is on by default, so a blank value must NOT exclude the ini:
# only explicit falsy values opt out (unlike auto_upload, which is opt-in
# and treats blank as off).
audit_version_str = section_items.get('auditversion') or section_items.get('audit_version')
if audit_version_str is not None:
metadata['audit_version'] = str(audit_version_str).strip().lower() not in ('false', '0', 'no', 'off')
Comment thread
SkrubbySkrubInAShrub marked this conversation as resolved.

section_metadata = {
'mod_id': section_items.get('nexusmodid') or section_items.get('nexus_mod_id') or section_items.get('mod_id'),
'mod_filename': section_items.get('nexusfilename') or section_items.get('nexus_filename') or section_items.get('nexusmodfilename') or section_items.get('nexus_mod_filename') or section_items.get('mod_filename') or section_items.get('modname') or section_items.get('name'),
Expand Down Expand Up @@ -630,6 +639,12 @@ def get_feature_key(feature_dir, feature_meta_map):

meta = feature_meta_map.get(feature_key)
ini_path = get_feature_ini(feature_dir)
# Activation-only features (e.g. Terrain Helper) opt out of version
# auditing via `AuditVersion = false` in their .ini: all their code lives
# in the core mod, so bumping the toggle .ini on every edit is meaningless
# churn. Skip them entirely from bump suggestions and PR-check failures.
if ini_path and not get_feature_ini_metadata(ini_path).get('audit_version', True):
continue
# Use last release tag (version_ref) as the baseline for version proposals so that
# multiple PRs between releases don't accumulate spurious bumps.
prior_ver = get_prior_version(ini_path, version_ref) if ini_path else None
Expand Down
Loading