This repository provides default community health files, reusable GitHub Actions workflows, templates, and shared documentation for the Schmiedmayer Lab organization.
This repository publishes reusable GitHub Actions workflows for common Schmiedmayer Lab project tasks.
Use them from another repository with jobs.<job_id>.uses and a version tag.
Each workflow documents its own inputs and secrets in its workflow_call block.
Where a value belongs:
| Scope | When to use it |
|---|---|
| Organization secret | The value is the same everywhere. Restrict it to the repositories that need it. |
| Repository secret | The value differs per repository and is not tied to a deployment target. |
| Environment secret | The value differs per deployment target, or the deployment should require approval. |
| Repository or environment variable | Not sensitive: project identifiers, bundle identifiers, feature flags. |
Deployment credentials belong on an environment. It is the only scope that can withhold a value until
a reviewer approves the run, and the only one where staging and production can hold different values
under the same name. A job that calls a reusable workflow cannot set environment: itself, so those
workflows declare it on their own jobs.
Encode binary material as Base64 and give the secret a _BASE64 suffix. Public repositories do not
need a Codecov token; private ones do.
Applied by scripts/apply-repository-settings.sh, which
audits and re-applies it. Run it after creating a repository.
| Setting | Value |
|---|---|
| Squash merge | the only merge method |
| Delete branch on merge | enabled |
| Wikis, Projects | disabled |
| Secret scanning and push protection | enabled on every public repository |
| Dependabot security updates | enabled |
| Dependabot version updates | grouped, weekly, via .github/dependabot.yml |
| Default workflow permissions | read |
| Required status checks | the four Standards / … contexts |
Because the default is read, a job starts with contents: read and packages: read and nothing
else. Declaring a permissions: block replaces that default rather than adding to it, so list
every scope the job needs. repository-standards.yml fails a pull request when a caller grants less
than the workflow it calls requires.
| Workflow | Use |
|---|---|
actionlint.yml |
Lint GitHub Actions workflow files with actionlint. |
eslint.yml |
Run ESLint for JavaScript and TypeScript projects. |
markdown-links.yml |
Check Markdown links. |
periphery.yml |
Run Periphery to detect unused Swift declarations. |
repository-standards.yml |
Check the organization repository baseline in one call. |
reuse.yml |
Check REUSE license and copyright metadata. |
swiftlint.yml |
Run SwiftLint for Swift style and quality checks. |
| Workflow | Use |
|---|---|
coverage.yml |
Merge coverage artifacts and upload the result to Codecov. |
docc-github-pages.yml |
Build DocC documentation and deploy it to GitHub Pages. |
swift-api-breaking-changes.yml |
Diagnose Swift API breaking changes with package metadata detection. |
swift-package-breaking-changes.yml |
Diagnose Swift package API breaking changes with explicit product and platform inputs. |
swift-package-ci.yml |
Run the standard Swift Package CI pipeline. |
swift-package-setup.yml |
Parse Swift package metadata for downstream workflows. |
swift-package-static-analysis.yml |
Run the standard static analysis checks for Swift packages. |
swift-package-test.yml |
Test a Swift package across the configured Apple and Linux matrices. |
swift-test.yml |
Run SwiftPM tests and optionally export LCOV coverage. |
xcodebuild.yml |
Build and test Apple projects with xcodebuild. |
xcodebuild-or-fastlane.yml |
Build, test, sign or deploy an Apple project through xcodebuild or a Fastlane lane. |
firebase-emulators-exec.yml |
Run a trusted command through the Firebase Emulator. |
xcode-deploy.yml |
Deploy Xcode projects with signing and file injection setup. |
xcarchive.yml |
Build an XCArchive and upload it as an artifact. |
xcframework.yml |
Build an XCFramework from XCArchive artifacts. |
xcframework-release.yml |
Commit and release an XCFramework artifact. |
| Workflow | Use |
|---|---|
android.yml |
Run the standard Android pipeline: Detekt, unit tests, CodeQL, screenshot tests, and instrumented tests. |
android-google-play.yml |
Sign an Android bundle and publish it to a Google Play track. |
android-google-play-bootstrap.yml |
Build the first signed bundle needed to create the Play Console listing. |
android-google-play-access.yml |
Verify that the Play service account can reach the application. |
| Workflow | Use |
|---|---|
firebase-deploy.yml |
Deploy Firebase projects. |
npm-pages.yml |
Build and deploy an npm project to GitHub Pages. |
npm-publish.yml |
Safely publish a fixed-version npm package or workspace release. |
npm-test-coverage.yml |
Test an npm package and upload coverage to Codecov. |
| Workflow | Use |
|---|---|
docker-build-and-push.yml |
Build and publish multi-architecture Docker images. |
docker-compose-test.yml |
Test a Docker Compose stack. |
| Workflow | Use |
|---|---|
action-release-tag.yml |
Maintain major and minor release tags for GitHub Actions repositories. |
format-release-notes.yml |
Format GitHub release notes. |
actionlint.yml installs actionlint and checks GitHub Actions workflow syntax.
Use it for repositories that maintain their own workflows.
jobs:
actionlint:
name: Lint GitHub Actions Workflows
uses: SchmiedmayerLab/.github/.github/workflows/actionlint.yml@v0.5
with:
runs_on_labels: '["ubuntu-latest"]'eslint.yml installs Node.js dependencies, runs the repository lint command, annotates pull requests, and uploads the ESLint report.
Use it for JavaScript and TypeScript projects with npm run lint:ci.
jobs:
eslint:
name: Run ESLint
uses: SchmiedmayerLab/.github/.github/workflows/eslint.yml@v0.5markdown-links.yml checks Markdown links with Linkspector.
Use it for documentation-heavy repositories. The workflow needs read access to pull requests so
Linkspector can map diagnostics to the pull request diff.
Linkspector browses anonymously, so in a private repository every link back into that repository
— badge targets, blob/main/LICENSE.md — answers 404 no matter what the file tree contains. The
workflow therefore adds an ignore pattern for the repository's own URL when the repository is
private, and leaves every other link checked.
jobs:
markdown-links:
name: Check Markdown Links
uses: SchmiedmayerLab/.github/.github/workflows/markdown-links.yml@v0.5
permissions:
contents: read
pull-requests: readperiphery.yml runs Periphery to detect unused Swift declarations.
Use it for Swift packages and Xcode projects that can be scanned from the repository root.
jobs:
periphery:
name: Run Periphery
uses: SchmiedmayerLab/.github/.github/workflows/periphery.yml@v0.5repository-standards.yml gives a repository the whole
organization baseline in one call: REUSE compliance, Markdown link health, and the repository surface
— required files, CITATION.cff, CONTRIBUTORS.md, badges, README structure, copyright holder, and
repository settings. See REPOSITORY_STANDARDS.md for the standard it
enforces.
Use it in every repository. It takes no inputs and there is no opt-out — every rule applies
everywhere.
name: Repository Standards
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
standards:
name: Standards
uses: SchmiedmayerLab/.github/.github/workflows/repository-standards.yml@v0.5reuse.yml checks that files carry REUSE-compliant license and copyright metadata.
Use it for repositories that follow the REUSE specification.
jobs:
reuse:
name: Check REUSE Compliance
uses: SchmiedmayerLab/.github/.github/workflows/reuse.yml@v0.5swiftlint.yml runs SwiftLint in strict mode.
Use it for Swift repositories that define SwiftLint rules.
jobs:
swiftlint:
name: Run SwiftLint
uses: SchmiedmayerLab/.github/.github/workflows/swiftlint.yml@v0.5coverage.yml downloads coverage artifacts, merges .xcresult and .lcov reports, and uploads the result to Codecov.
Use it after test jobs that upload coverage artifacts.
jobs:
coverage:
name: Merge and Upload Coverage
uses: SchmiedmayerLab/.github/.github/workflows/coverage.yml@v0.5
with:
coveragereports: ResultBundle1.xcresult ResultBundle2.xcresult
secrets:
token: ${{ secrets.CODECOV_TOKEN }}docc-github-pages.yml builds DocC documentation with xcodebuild and deploys the generated site to GitHub Pages.
Use it for Swift packages and Xcode projects that publish API documentation.
permissions:
contents: read
pages: write
id-token: write
jobs:
docc:
name: Deploy DocC Documentation
uses: SchmiedmayerLab/.github/.github/workflows/docc-github-pages.yml@v0.5
with:
scheme: ExamplePackageswift-api-breaking-changes.yml detects library products and platform metadata before running Swift API breakage diagnostics.
Use it for Swift packages that can rely on automatic metadata detection.
jobs:
api-breaking-changes:
name: Diagnose Swift API Breaking Changes
uses: SchmiedmayerLab/.github/.github/workflows/swift-api-breaking-changes.yml@v0.5swift-package-breaking-changes.yml runs Swift API breakage diagnostics with explicit library product and platform inputs.
Use it when another workflow already knows the package metadata.
jobs:
package-breaking-changes:
name: Diagnose Swift Package API Breaking Changes
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-breaking-changes.yml@v0.5
with:
library_products: '["ExamplePackage"]'
platform_name: ios
platform_version: '18.0'Use swift-package-ci.yml as the default entry point for Swift packages.
It detects package metadata, runs tests, uploads coverage when available, and runs static analysis.
jobs:
swift-package-ci:
name: Swift Package CI
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-ci.yml@v0.5
secrets: inheritswift-package-setup.yml parses Swift package metadata and exposes it as workflow outputs.
Use it as a setup job before lower-level Swift package workflows.
jobs:
setup:
name: Set Up Swift Package
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-setup.yml@v0.5
test:
name: Test Swift Package
needs: setup
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-test.yml@v0.5
with:
package_name: ${{ needs.setup.outputs.package_name }}
scheme: ${{ needs.setup.outputs.scheme }}
platform_matrix: ${{ needs.setup.outputs.platform_matrix }}
ui_platform_matrix: ${{ needs.setup.outputs.ui_platform_matrix }}swift-package-static-analysis.yml combines REUSE, SwiftLint, Markdown link checking, and Swift API breakage diagnostics.
Use it when package metadata is already available from swift-package-setup.yml.
jobs:
analyze:
name: Analyze Swift Package
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-static-analysis.yml@v0.5
with:
library_products: '["ExamplePackage"]'
platform_name: ios
platform_version: '18.0'swift-package-test.yml runs Apple platform test matrices, optional UI test matrices, optional Linux tests, and coverage upload.
Use it when package metadata and platform matrices are provided explicitly.
jobs:
test:
name: Test Swift Package
uses: SchmiedmayerLab/.github/.github/workflows/swift-package-test.yml@v0.5
with:
package_name: ExamplePackage
scheme: ExamplePackage
platform_matrix: >-
[{"name":"iOS","destination":"platform=iOS Simulator,name=iPhone 17 Pro"}]
ui_platform_matrix: '[]'
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}swift-test.yml runs SwiftPM tests and can upload an LCOV artifact for later coverage merging.
Use it for Linux Swift package tests or simple SwiftPM test jobs.
jobs:
swift-test:
name: Run Swift Tests
uses: SchmiedmayerLab/.github/.github/workflows/swift-test.yml@v0.5Use xcodebuild.yml for Apple projects that need direct xcodebuild tests or builds.
When scheme is omitted, the workflow infers the Swift package scheme from Package.swift or the only shared Xcode scheme in the selected path.
Swift packages use the package name as the scheme, or PackageName-Package when the package defines multiple library products.
Swift package result bundles use PackageName.xcresult in both cases.
Test runs upload the resolved .xcresult bundle automatically; set resultBundle only when you need a custom bundle name.
The workflow intentionally does not declare its own permissions block because its CodeQL path is optional.
Callers that set codeql: true must grant security-events: write; normal build and test jobs can omit that permission.
jobs:
app-tests:
name: Build and Test App
permissions:
contents: read
uses: SchmiedmayerLab/.github/.github/workflows/xcodebuild.yml@v0.5
with:
runsonlabels: '["macOS", "self-hosted"]'
package-tests:
name: Build and Test Swift Package
uses: SchmiedmayerLab/.github/.github/workflows/xcodebuild.yml@v0.5
with:
path: ExamplePackage
runsonlabels: '["macOS", "self-hosted"]'CodeQL analysis uses the same workflow with codeql: true.
Because GitHub sets unspecified token scopes to none when any explicit permission is declared, grant both contents: read and security-events: write on the calling job.
When CodeQL runs on a GitHub-hosted runner, the workflow builds the project without running tests even though test defaults to true.
jobs:
codeql:
name: Build and Analyze with CodeQL
permissions:
contents: read
security-events: write
uses: SchmiedmayerLab/.github/.github/workflows/xcodebuild.yml@v0.5
with:
codeql: true
scheme: TemplatePackagexcodebuild-or-fastlane.yml is the general-purpose
Apple build workflow. It runs xcodebuild by default, or a named Fastlane lane instead, and can
optionally set up code signing, a Firebase emulator, CodeQL, and injected configuration files.
jobs:
buildandtest:
name: Build and Test
uses: SchmiedmayerLab/.github/.github/workflows/xcodebuild-or-fastlane.yml@v0.5
permissions:
contents: read
with:
scheme: MyAppUse firebase-emulators-exec.yml for test or validation commands that must run while Firebase emulators are active.
The command input is executed through firebase emulators:exec and can be any trusted shell command.
Use artifact_path to upload command output such as an .xcresult bundle; the artifact name is inferred from the path.
jobs:
firebase-ui-tests:
name: Run UI Tests with Firebase Emulator
uses: SchmiedmayerLab/.github/.github/workflows/firebase-emulators-exec.yml@v0.5
with:
command: bundle exec fastlane uitest
artifact_path: fastlane/test_output/UITests.xcresult
firebase_emulator_import: ./firebase-export
secrets:
GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}Use xcode-deploy.yml for Xcode deployments that need code signing, App Store Connect environment variables, or a Base64-encoded secret file written before deployment.
The injected_secret_file_path input defines the injected file path, name, and extension.
The workflow does not start Firebase emulators and does not validate that command is a fastlane command.
Use fastlane, bundle exec fastlane, or another trusted deployment command.
jobs:
deploy:
name: Deploy Xcode Project
permissions:
contents: read
uses: SchmiedmayerLab/.github/.github/workflows/xcode-deploy.yml@v0.5
with:
command: >-
bundle exec fastlane deploy environment:"staging"
versionname:"4.0.5" releasenotes:"Test Deployment."
environment: staging
setup_signing: true
injected_secret_file_path: App/DeploymentConfiguration.json
secrets:
APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }}
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
INJECTED_SECRET_FILE_BASE64: ${{ secrets.DEPLOYMENT_CONFIGURATION_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}xcarchive.yml builds an XCArchive and uploads it as an artifact.
Use it for binary distribution pipelines that package Apple platform archives.
jobs:
xcarchive:
name: Build XCArchive
uses: SchmiedmayerLab/.github/.github/workflows/xcarchive.yml@v0.5
with:
workspaceFile: example.xcworkspace
xcArchiveName: ExampleKit
scheme: ExampleKit
version: 0.1.0Use xcframework.yml to package XCArchive outputs into an XCFramework artifact.
jobs:
xcframework:
name: Build XCFramework
uses: SchmiedmayerLab/.github/.github/workflows/xcframework.yml@v0.5
with:
workspaceFile: example.xcworkspace
xcFrameworkName: ExampleKit
scheme: ExampleKit
version: 0.1.0xcframework-release.yml downloads built XCFramework artifacts, commits them to the repository, tags the release, and creates a GitHub release.
Use it after xcframework.yml has produced the XCFramework artifact.
permissions:
actions: read
contents: write
jobs:
release-xcframework:
name: Release XCFramework
uses: SchmiedmayerLab/.github/.github/workflows/xcframework-release.yml@v0.5
with:
version: v0.2
secrets:
access-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}android.yml runs Detekt, unit tests, CodeQL, screenshot tests and
instrumented tests. It reads the JDK, the Ruby version, the Detekt configuration and the available
Fastlane lanes from the project, so a conventional repository passes no inputs.
jobs:
android:
name: Android
uses: SchmiedmayerLab/.github/.github/workflows/android.yml@v0.5
permissions:
actions: read
contents: read
packages: read
security-events: write
secrets: inheritandroid-google-play.yml signs the app and publishes it
to a Google Play track. Name the deployment environments after the tracks — internal, alpha,
beta, production — so the environment carries that track's credentials and track never has to
be passed.
google_play:
name: Google Play Upload
needs: android
uses: SchmiedmayerLab/.github/.github/workflows/android-google-play.yml@v0.5
permissions:
contents: read
secrets: inherit
with:
environment: internalandroid-google-play-bootstrap.yml builds the
first signed bundle, which Google Play requires before a listing exists, and uploads it as an
artifact.
signed_bundle:
name: Signed Bootstrap Bundle
needs: android
uses: SchmiedmayerLab/.github/.github/workflows/android-google-play-bootstrap.yml@v0.5
permissions:
contents: read
secrets: inherit
with:
version: 1.0.0android-google-play-access.yml checks that the
Play service account can reach the application. Run it before a release, or after rotating
credentials.
google_play_access:
name: Google Play Access
uses: SchmiedmayerLab/.github/.github/workflows/android-google-play-access.yml@v0.5
permissions:
contents: read
secrets: inheritfirebase-deploy.yml installs Firebase tooling and deploys a Firebase project with service-account credentials.
Use it for Firebase Hosting, Functions, Firestore rules, or other Firebase deploy targets.
jobs:
firebase:
name: Deploy Firebase
uses: SchmiedmayerLab/.github/.github/workflows/firebase-deploy.yml@v0.5
with:
arguments: --only hosting
secrets:
GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}Use npm-publish.yml for repositories that publish one package or a fixed-version npm workspace collection.
The workflow reads a published GitHub release tag, Node.js from .nvmrc, and npm from the exact packageManager entry in package.json, so release-event callers normally provide no inputs.
It validates bare semantic versions, orders workspace packages by runtime dependencies, synchronizes internal dependency versions, skips versions already present on npm, publishes existing packages through OIDC, and verifies the registry state.
Keep the top-level caller at .github/workflows/deployment.yml.
npm validates the caller workflow name when a reusable workflow performs the publication, and every Trusted Publisher must authorize deployment.yml.
permissions:
contents: read
id-token: write
jobs:
publish:
uses: SchmiedmayerLab/.github/.github/workflows/npm-publish.yml@v0.5Manual release callers pass their dispatch input as packageVersion.
For the first publication of a new package, temporarily pass its package name in bootstrapPackages and expose a short-lived granular NPM_TOKEN with read/write scope access and Bypass two-factor authentication enabled.
The token is available only to the bootstrap step.
After publication, the workflow summary provides the interactive npm trust commands required to authorize deployment.yml with npm 11.15.0 or later; remove the token after a subsequent OIDC publication succeeds.
Repositories may define an optional release:prepare script for package-specific preparation after versions are synchronized.
The workflow automatically runs build, pack:check, and pack:lint when those scripts exist.
Callers pinned to an earlier release continue to use the earlier interface unchanged.
When adopting v0.5, remove the former runtime, workspace, and npm-tag inputs because the workflow now reads the runtime from the repository, discovers workspaces, and selects latest or next from the version.
Replace bootstrapWithToken: true with explicit package names in bootstrapPackages, or use * only when every unpublished package is intentionally being bootstrapped.
Use npm-pages.yml when an npm project can build its complete Pages artifact with npm run pages:build.
By default, the script must create deploy/index.html; when artifactPath is set, it must create <artifactPath>/index.html.
All routing and framework-specific build decisions stay in the caller repository.
By default, Node.js is read from .nvmrc and npm from the exact root packageManager entry.
permissions:
contents: read
pages: write
id-token: write
jobs:
pages:
uses: SchmiedmayerLab/.github/.github/workflows/npm-pages.yml@v0.5Call npm run pages:build directly in pull-request CI so that build jobs do not receive deployment permissions.
nodeVersionFile and artifactPath are available only for repositories that cannot follow the default conventions.
This convention also supports static Next.js exports, replacing the former framework-specific workflow.
Existing callers can remain on their pinned Next.js workflow release until their repository provides pages:build and adopts npm-pages.yml@v0.5.
Use npm-test-coverage.yml for npm projects that should run npm ci, npm test, and upload coverage to Codecov.
It reads Node.js from .nvmrc and npm from the exact packageManager entry in the selected project's package.json, so the standard caller does not provide runtime versions.
Set coverage-files to a comma-separated list when a repository contains non-coverage files whose names could be discovered by Codecov.
Firebase projects can enable emulator tooling with setup-firebase-emulator: true; callers must install firebase-tools through package-lock.json, which also keys the emulator cache.
jobs:
npm-test:
name: Test npm Package and Upload Coverage
uses: SchmiedmayerLab/.github/.github/workflows/npm-test-coverage.yml@v0.5
with:
coverage-files: coverage/lcov.info
secrets:
token: ${{ secrets.CODECOV_TOKEN }}Use docker-build-and-push.yml to publish a multi-architecture Docker image.
permissions:
contents: read
packages: write
jobs:
docker:
name: Build and Push Docker Image
uses: SchmiedmayerLab/.github/.github/workflows/docker-build-and-push.yml@v0.5
with:
imageName: schmiedmayerlab/exampledocker-compose-test.yml builds and starts a Docker Compose stack and can run an optional smoke-test script.
Use it for projects where integration tests run against local services.
jobs:
docker-compose:
name: Test Docker Compose Stack
uses: SchmiedmayerLab/.github/.github/workflows/docker-compose-test.yml@v0.5
with:
testscript: scripts/smoke-test.shUse action-release-tag.yml for GitHub Actions repositories that publish semantic version tags.
For example, publishing v2.4.2 can also update v2 and v2.4.
permissions:
contents: write
jobs:
release-tags:
name: Tag Action Release
uses: SchmiedmayerLab/.github/.github/workflows/action-release-tag.yml@v0.5
secrets:
access-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
with:
user: PaulsAutomationBotformat-release-notes.yml fetches a GitHub release and formats its release notes for downstream release automation.
Use it when another job needs the formatted notes from the releasenotes output.
jobs:
release-notes:
name: Format Release Notes
uses: SchmiedmayerLab/.github/.github/workflows/format-release-notes.yml@v0.5
with:
release-tag: ${{ github.ref_name }}
repository: ${{ github.repository }}Contributions to this project are welcome. Please make sure to read the contribution guidelines and the contributor covenant code of conduct first. You can find a list of contributors in the CONTRIBUTORS.md file.
This project is licensed under the MIT License. See LICENSE.md for more information.
If you use this software, please cite it using the metadata in CITATION.cff, which GitHub surfaces through the Cite this repository button.
For more information, visit the Schmiedmayer Lab GitHub organization.

