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
14 changes: 14 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ through the repository API. Their profiles are `release_notifications`, `flathub
selections disable that workflow group; invalid values or failed property reads fail the check. These runtime
checks are independent of the file replicator's `sync_mode` setting.

The `__call-organization.yml` reusable workflow exports an `allowed` output based on the caller's
owner and the trusted `LizardByte/.github/master/organizations.json` registry. It needs no custom secrets
or repository permissions and fails if the registry cannot be read or validated. New organizations only
need to be added to that registry. Consumer workflows use this check for publishing, coverage uploads,
and organization automation; ordinary test builds remain available to unregistered forks. The controller's
own maintenance jobs retain their repository restrictions.

Shared publishing destinations remain in LizardByte, including the website, Homebrew tap, pacman repository,
Docker/GHCR namespace, npm scope, and WinGet identifiers. Docker callers can override `image_namespace` if
they publish elsewhere. WinGet uses the configured bot's fork. Cross-organization GitHub npm publishing
requires `GH_TOKEN` with `write:packages` access to the existing LizardByte packages; the replicated wrapper
passes `GH_BOT_TOKEN`. npmjs trusted-publisher bindings and external service installations must also be
updated for the destination owner when transferring a repository.

Repositories excluded from the GitLab mirror are listed in `.github/repositories-to-ignore.json`.

The GitLab mirror also excludes GitHub temporary security advisory forks matching
Expand Down
13 changes: 10 additions & 3 deletions .github/workflows/__call-ci-node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ on:
required: false

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

setup_release:
needs: organization
name: Setup Release
outputs:
publish_release: ${{ steps.setup_release.outputs.publish_release }}
publish_release: >-
${{ needs.organization.outputs.allowed == 'true' &&
steps.setup_release.outputs.publish_release == 'true' }}
release_body: ${{ steps.setup_release.outputs.release_body }}
release_generate_release_notes: ${{ steps.setup_release.outputs.release_generate_release_notes }}
release_tag: ${{ steps.setup_release.outputs.release_tag }}
Expand All @@ -47,6 +53,7 @@ jobs:
build:
needs:
- setup_release
- organization
permissions:
contents: read
runs-on: ubuntu-latest
Expand Down Expand Up @@ -98,7 +105,7 @@ jobs:
if: >-
always() &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure') &&
startsWith(github.repository, 'LizardByte/')
needs.organization.outputs.allowed == 'true'
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
disable_search: true
Expand All @@ -113,7 +120,7 @@ jobs:
if: >-
always() &&
(steps.test.outcome == 'success' || steps.test.outcome == 'failure') &&
startsWith(github.repository, 'LizardByte/')
needs.organization.outputs.allowed == 'true'
uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
with:
fail_ci_if_error: true
Expand Down
33 changes: 23 additions & 10 deletions .github/workflows/__call-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ on:
pull_request:
workflow_call:
inputs:
image_namespace:
description: 'Existing namespace for Docker Hub and GHCR images.'
required: false
default: 'LizardByte'
type: string
docker_hub_username:
description: 'Docker Hub username to use for the workflow.'
required: false
Expand Down Expand Up @@ -60,7 +65,11 @@ on:
required: false

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

check_dockerfiles:
needs: organization
name: Plan Docker builds
permissions:
contents: read
Expand Down Expand Up @@ -173,13 +182,16 @@ jobs:
- name: Set image name
id: additional_outputs
if: steps.find.outputs.has_bake == 'true'
env:
IMAGE_NAMESPACE: ${{ inputs.image_namespace || 'LizardByte' }}
REPOSITORY_NAME: ${{ github.event.repository.name }}
run: |
# set outputs for later jobs
REPOSITORY="${{ github.repository }}"
BASE_TAG=$(echo ${REPOSITORY} | tr '[:upper:]' '[:lower:]')
BASE_TAG=$(printf '%s/%s' "${IMAGE_NAMESPACE}" "${REPOSITORY_NAME}" | tr '[:upper:]' '[:lower:]')
echo "base_tag=${BASE_TAG}" >> "${GITHUB_OUTPUT}"

outputs:
publish_release: ${{ needs.organization.outputs.allowed == 'true' && inputs.publish_release == 'true' }}
bake_build_matrix: ${{ steps.find.outputs.bake_build_matrix }}
bake_target_matrix: ${{ steps.find.outputs.bake_target_matrix }}
base_tag: ${{ steps.additional_outputs.outputs.base_tag }}
Expand All @@ -197,13 +209,13 @@ jobs:
environment:
name: >-
${{
inputs.publish_release == 'true' &&
needs.check_dockerfiles.outputs.publish_release == 'true' &&
format('docker{0}', matrix.tag) ||
null
}}
url: >-
${{
inputs.publish_release == 'true' &&
needs.check_dockerfiles.outputs.publish_release == 'true' &&
format('https://hub.docker.com/r/{0}/tags?name={1}',
needs.check_dockerfiles.outputs.base_tag, matrix.tag) ||
null
Expand All @@ -230,7 +242,7 @@ jobs:
BRANCH: ${{ github.ref }}
COMMIT: ${{ inputs.release_commit }}
GH_EVENT_REPOSITORY_CLONE_URL: ${{ github.event.repository.clone_url }}
PUBLISH_RELEASE: ${{ inputs.publish_release }}
PUBLISH_RELEASE: ${{ needs.check_dockerfiles.outputs.publish_release }}
RELEASE_VERSION: ${{ inputs.release_version }}
USE_CACHE: ${{ matrix.cache }}
shell: bash
Expand Down Expand Up @@ -280,14 +292,14 @@ jobs:
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1

- name: Log in to Docker Hub
if: inputs.publish_release == 'true' # PRs do not have access to secrets
if: needs.check_dockerfiles.outputs.publish_release == 'true' # PRs do not have access to secrets
uses: docker/login-action@8aa5831fb8d48d8f76594c7ddde61ae58019f550 # v4.8.0
with:
username: ${{ inputs.docker_hub_username }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

- name: Log in to the Container registry
if: inputs.publish_release == 'true' # PRs do not have access to secrets
if: needs.check_dockerfiles.outputs.publish_release == 'true' # PRs do not have access to secrets
uses: docker/login-action@8aa5831fb8d48d8f76594c7ddde61ae58019f550 # v4.8.0
with:
registry: ghcr.io
Expand Down Expand Up @@ -340,7 +352,7 @@ jobs:
if-no-files-found: error

- name: Export digest
if: inputs.publish_release == 'true'
if: needs.check_dockerfiles.outputs.publish_release == 'true'
env:
BUILD_METADATA: ${{ steps.build.outputs.metadata }}
shell: bash
Expand All @@ -356,7 +368,7 @@ jobs:
touch "digests/${digest#sha256:}"

- name: Upload digest
if: inputs.publish_release == 'true'
if: needs.check_dockerfiles.outputs.publish_release == 'true'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: docker-digests-${{ matrix.target }}-${{ matrix.platform_pair }}
Expand All @@ -366,7 +378,7 @@ jobs:

docker_bake_manifest:
name: Manifest
if: inputs.publish_release == 'true'
if: needs.check_dockerfiles.outputs.publish_release == 'true'
needs:
- check_dockerfiles
- docker_bake
Expand Down Expand Up @@ -471,6 +483,7 @@ jobs:
release:
name: Release
if: >
needs.check_dockerfiles.outputs.publish_release == 'true' &&
github.event_name == 'push' &&
github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/__call-organization.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: Check organization (called)
permissions: {}

on:
workflow_call:
outputs:
allowed:
description: Whether the caller belongs to the shared organization registry.
value: ${{ jobs.check.outputs.allowed }}

jobs:
check:
runs-on: ubuntu-latest
outputs:
allowed: ${{ steps.registry.outputs.allowed }}
steps:
- name: Check trusted organization registry
id: registry
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const response = await fetch(
'https://raw.githubusercontent.com/LizardByte/.github/master/organizations.json',
{signal: AbortSignal.timeout(15000)},
);
if (!response.ok) throw new Error(`Organization registry request failed: HTTP ${response.status}`);
const organizations = await response.json();
if (!Array.isArray(organizations) || !organizations.length || organizations.some(name =>
typeof name !== 'string' || !/^[a-z\d][a-z\d-]*$/i.test(name))) {
throw new Error('Invalid organization registry');
}
const allowed = organizations.some(name => name.toLowerCase() === context.repo.owner.toLowerCase());
core.info(`Organization ${context.repo.owner}: ${allowed ? 'registered' : 'not registered'}`);
core.setOutput('allowed', allowed);
8 changes: 6 additions & 2 deletions .github/workflows/__call-release-notifier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,21 @@ on:
required: true

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

update-blog:
needs: organization
name: Update blog
if: github.repository_owner == 'LizardByte'
if: needs.organization.outputs.allowed == 'true'
permissions:
contents: read
runs-on: ubuntu-latest
environment:
name: release-announcement
url: ${{ steps.create-pr.outputs.pull-request-url }}
env:
BLOG_REPO: ${{ github.repository_owner }}/${{ github.repository_owner }}.github.io
BLOG_REPO: LizardByte/LizardByte.github.io
steps:
- name: Check workflow profile
env:
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/__call-top-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ on:
workflow_call:

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

top-issues:
needs: organization
if: needs.organization.outputs.allowed == 'true'
name: Top issues
permissions:
contents: read
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/__call-update-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ on:
required: true

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

update-changelog:
needs: organization
if: needs.organization.outputs.allowed == 'true'
name: Update Changelog
permissions:
contents: read
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/__call-update-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ on:
required: true

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

update-docs:
needs: organization
environment:
name: ReadTheDocs
url: https://${{ steps.get_slug.outputs.RTD_SLUG }}.readthedocs.io//latest
Expand All @@ -25,6 +29,7 @@ jobs:
RTD_TOKEN: ${{ secrets.READTHEDOCS_TOKEN }}
TAG: ${{ github.event.release.tag_name }}
if: >-
needs.organization.outputs.allowed == 'true' &&
!github.event.release.draft
permissions: {}
runs-on: ubuntu-latest
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/__call-update-flathub-repo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ on:
required: true

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

update-flathub-repo:
needs: organization
if: needs.organization.outputs.allowed == 'true'
environment:
name: Flathub
url: ${{ steps.create-pr.outputs.pull-request-url }}
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/__call-update-homebrew-repo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@ on:
required: true

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

update-homebrew-repo:
needs: organization
if: needs.organization.outputs.allowed == 'true'
permissions:
contents: read
runs-on: ubuntu-latest
environment:
name: Homebrew
url: https://github.com/${{ github.repository_owner }}/homebrew-homebrew/commits
url: https://github.com/LizardByte/homebrew-homebrew/commits
steps:
- name: Check workflow profile
id: check-profile
Expand Down Expand Up @@ -68,5 +73,6 @@ jobs:
git_email: ${{ secrets.GH_EMAIL }}
git_username: ${{ inputs.gh_username }}
publish: true
org_homebrew_repo: LizardByte/homebrew-homebrew
token: ${{ secrets.GH_TOKEN }}
validate: false
19 changes: 16 additions & 3 deletions .github/workflows/__call-update-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ permissions: {}

on:
workflow_call:
secrets:
GH_TOKEN:
description: Token with write access to the existing GitHub Packages namespace.
required: false
inputs:
release_version:
description: 'Version to publish (v prefix will be stripped automatically).'
required: true
type: string

jobs:
organization:
uses: ./.github/workflows/__call-organization.yml

publish-npm:
needs: organization
if: needs.organization.outputs.allowed == 'true'
permissions:
contents: read
id-token: write # required for provenance and OIDC
Expand All @@ -36,9 +45,13 @@ jobs:

- name: Setup token
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ github.repository_owner == 'LizardByte' && secrets.GITHUB_TOKEN || secrets.GH_TOKEN }}
run: |
if [[ "${{ matrix.environment }}" == "npm-gpr" ]]; then
if [[ -z "${GH_TOKEN}" ]]; then
echo "::error::GitHub Packages publishing requires GH_TOKEN with write:packages access to LizardByte."
exit 1
fi
echo "NODE_AUTH_TOKEN=${GH_TOKEN}" >> "${GITHUB_ENV}"
fi

Expand Down Expand Up @@ -72,10 +85,10 @@ jobs:
- name: Set environment output
id: environment
run: |
package_name=$(node -p "require('./package.json').name")
if [[ "${{ matrix.environment }}" == "npm-gpr" ]]; then
url="https://github.com/${{ github.repository }}/pkgs/npm/${{ github.event.repository.name }}"
url="https://github.com/orgs/LizardByte/packages/npm/${package_name#@lizardbyte/}"
elif [[ "${{ matrix.environment }}" == "npmjs" ]]; then
package_name=$(node -p "require('./package.json').name")
url="https://www.npmjs.com/package/${package_name}"
fi
echo "url=${url}" >> "${GITHUB_OUTPUT}"
Loading
Loading