diff --git a/.github/DISCUSSION_TEMPLATE/challenges-and-help.yml b/.github/DISCUSSION_TEMPLATE/challenges-and-help.yml index a85fa38..9b5004e 100644 --- a/.github/DISCUSSION_TEMPLATE/challenges-and-help.yml +++ b/.github/DISCUSSION_TEMPLATE/challenges-and-help.yml @@ -36,12 +36,12 @@ body: id: reproduction attributes: label: Reproduction - description: | + description: | Please provide a description of how to reproduce the problem you are facing. - + If you are facing a problem in your application, please provide a link to a failing UI test or unit test to reproduce the issue. - If you face a build error or a problem with releasing your application, please link a GitHub Action run reproducing the error outside of your development. - placeholder: | + If you face a build error or a problem with releasing your application, please link a GitHub Action run reproducing the error. + placeholder: | What steps did you follow to get the problem? Provide links and steps on how to reproduce the problem. validations: @@ -58,14 +58,14 @@ body: id: additionalcontext attributes: label: Additional context - description: | + description: | Please provide any additional context that might be relevant to your setup problem. placeholder: Any additional context that might be relevant to your problem. - type: checkboxes id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this projects's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/DISCUSSION_TEMPLATE/ideas.yml b/.github/DISCUSSION_TEMPLATE/ideas.yml index d7a207a..d0f0485 100644 --- a/.github/DISCUSSION_TEMPLATE/ideas.yml +++ b/.github/DISCUSSION_TEMPLATE/ideas.yml @@ -61,12 +61,12 @@ body: attributes: label: Alternatives considered description: | - Please provide a clear and concise description of any alternative solutions or features you've considered. - + Please provide a clear and concise description of any alternative solutions or features you've considered. + Is there already software that has the behavior you're interested in? What is it, and how does it work? placeholder: | - A clear and concise description of any alternative solutions or features you've considered. - + A clear and concise description of any alternative solutions or features you've considered. + Is there already software that has the behavior you're interested in? What is it, and how does it work? validations: required: true @@ -74,13 +74,13 @@ body: id: additionalcontext attributes: label: Additional context - description: Please provide any additional context that might be relevant for your feature report - placeholder: Any additional context that might be relevant for your feature report + description: Please provide any additional context that might be relevant for your feature report. + placeholder: Any additional context that might be relevant for your feature report. - type: checkboxes id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this projects's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/DISCUSSION_TEMPLATE/show-and-tell.yml b/.github/DISCUSSION_TEMPLATE/show-and-tell.yml index d801167..5f0f419 100644 --- a/.github/DISCUSSION_TEMPLATE/show-and-tell.yml +++ b/.github/DISCUSSION_TEMPLATE/show-and-tell.yml @@ -20,7 +20,7 @@ body: description: | Please provide a description of your project and the software you have developed! Share your background, motivation for your project, and additional scientific background. - + Feel free to share screenshots, videos, and examples demonstrating your project. placeholder: A descriptive overview of your project, including images, videos, and examples. validations: @@ -29,9 +29,9 @@ body: id: contact attributes: label: Contact Information and Additional Context - description: | + description: | Feel free to share some contact information and additional links to your project! - placeholder: | + placeholder: | Your contact information and additional context. validations: required: true @@ -39,7 +39,7 @@ body: id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this projects's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index f09e9d7..5e577c1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -49,7 +49,7 @@ body: id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this project's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/ISSUE_TEMPLATE/internal_change.yml b/.github/ISSUE_TEMPLATE/internal_change.yml index bc6b336..8007548 100644 --- a/.github/ISSUE_TEMPLATE/internal_change.yml +++ b/.github/ISSUE_TEMPLATE/internal_change.yml @@ -41,7 +41,7 @@ body: id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this project's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/ISSUE_TEMPLATE/major_feature.yml b/.github/ISSUE_TEMPLATE/major_feature.yml index 8c404a3..281a4ef 100644 --- a/.github/ISSUE_TEMPLATE/major_feature.yml +++ b/.github/ISSUE_TEMPLATE/major_feature.yml @@ -43,8 +43,12 @@ body: id: alternatives attributes: label: Alternatives considered - description: Please provide a clear and concise description of any alternative solutions or features you've considered. Is there already software that has the behavior you're interested in? What is it, and how does it work? - placeholder: A clear and concise description of any alternative solutions or features you've considered. Is there already software that has the behavior you're interested in? What is it, and how does it work? + description: | + Please provide a clear and concise description of any alternative solutions or features you've considered. + Is there already software that has the behavior you're interested in? What is it, and how does it work? + placeholder: | + A clear and concise description of any alternative solutions or features you've considered. + Is there already software that has the behavior you're interested in? What is it, and how does it work? validations: required: true - type: textarea @@ -57,7 +61,7 @@ body: id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this project's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/ISSUE_TEMPLATE/minor_feature.yml b/.github/ISSUE_TEMPLATE/minor_feature.yml index 439f2a7..21d779e 100644 --- a/.github/ISSUE_TEMPLATE/minor_feature.yml +++ b/.github/ISSUE_TEMPLATE/minor_feature.yml @@ -41,7 +41,7 @@ body: id: terms attributes: label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) + description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md) # yamllint disable-line rule:line-length options: - label: I agree to follow this project's Code of Conduct and Contributing Guidelines required: true diff --git a/.github/codecov.yml b/.github/codecov.yml index b2694c7..05aec8b 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -7,11 +7,11 @@ # ignore: -- "Tests" -- "Example" + - "Tests" + - "Example" codecov: - require_ci_to_pass: yes + require_ci_to_pass: true bot: PaulsAutomationBot branch: main @@ -38,12 +38,12 @@ coverage: parsers: gcov: branch_detection: - conditional: yes - loop: yes - method: no - macro: no + conditional: true + loop: true + method: false + macro: false comment: layout: "reach,diff,flags,files,footer" behavior: default - require_changes: no + require_changes: false diff --git a/.github/workflows/action-release-tag.yml b/.github/workflows/action-release-tag.yml index 43dc086..2a6c019 100644 --- a/.github/workflows/action-release-tag.yml +++ b/.github/workflows/action-release-tag.yml @@ -12,13 +12,15 @@ on: workflow_call: inputs: user: - description: 'Optional GitHub username that is associated with the GitHub Personal Access Token (PAT)' + description: | + Optional GitHub username that is associated with the GitHub Personal Access Token (PAT) type: string required: false default: '' secrets: access-token: - description: 'GitHub Personal Access Token (PAT) if the default branch is protected and needs a specific access token to push tags to the branch' + description: | + GitHub Personal Access Token (PAT) if the default branch is protected and needs a specific access token to push tags to the branch required: false jobs: @@ -44,12 +46,12 @@ jobs: MINOR=${VERSION%.*} echo "Push Tags $MAJOR and $MINOR for $VERSION" - + git config user.name "${{ inputs.user || github.actor }}" git config user.email "${{ inputs.user || github.actor }}@users.noreply.github.com" - + git switch --detach ${VERSION} - + git push origin :refs/tags/${MAJOR} git tag -fa "${MAJOR}" -m "${MAJOR}" git push origin --tags diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index e376a80..3408cd6 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -12,39 +12,49 @@ on: workflow_call: inputs: workspaceFile: - description: 'The path of the Xcode Workspace file (including the file extension).' + description: | + The path of the Xcode Workspace file (including the file extension). type: string required: true xcArchiveName: - description: 'The name of the to be created XCArchive. It must not include the default XCArchive extension ".xcarchive" as the file naming is automatically done be the workflow.' + description: | + The name of the to be created XCArchive. + It must not include the default XCArchive extension ".xcarchive" as the file naming is automatically done be the workflow. type: string required: true scheme: - description: 'The project scheme that should be used for the archiving process.' + description: | + The project scheme that should be used for the archiving process. type: string required: true version: - description: 'The version number of the XCFramework embedded in the XCArchives.' + description: | + The version number of the XCFramework embedded in the XCArchives. type: string required: false default: 'ci' configuration: - description: 'The build configuration to use when archiving the scheme, either Debug or Release.' + description: | + The build configuration to use when archiving the scheme, either Debug or Release. type: string required: false default: 'Release' runsonlabels: - description: 'JSON-based collection of labels indicating which type of github runner should be chosen.' + description: | + JSON-based collection of labels indicating which type of github runner should be chosen. type: string required: false default: '["macos-14"]' sdk: - description: 'JSON-based collection of SDK for the exported framework. Defaults to all SDKs. You can list SDKs using `xcodebuild -showsdks`.' + description: | + JSON-based collection of SDK for the exported framework. Defaults to all SDKs. + You can list SDKs using `xcodebuild -showsdks`. type: string required: false default: '["iphoneos", "iphonesimulator", "macosx", "appletvos", "appletvsimulator", "xros", "xrsimulator", "watchos", "watchsimulator"]' cxxInterop: - description: 'Enable the compilation of the XCArchive with active Swift / C++ interoperability.' + description: | + Enable the compilation of the XCArchive with active Swift / C++ interoperability. type: boolean required: false default: false @@ -57,40 +67,40 @@ jobs: matrix: sdk: ${{ fromJson(inputs.sdk) }} steps: - - uses: actions/checkout@v4 - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - name: Check environment - run: | - xcodebuild -version - swift --version - echo Release version: ${{ inputs.version }} - echo SDK: ${{ matrix.sdk }} - - name: Install xcbeautify - if: ${{ !env.selfhosted && inputs.scheme != '' }} - run: brew install xcbeautify - - name: Archive for ${{ matrix.sdk }} SDK - run: | - xcodebuild archive \ - -workspace ${{ inputs.workspaceFile }} \ - -scheme ${{ inputs.scheme }} \ - -configuration ${{ inputs.configuration }} \ - -sdk ${{ matrix.sdk }} \ - -archivePath './.build/${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive' \ - SKIP_INSTALL=NO \ - BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ - ONLY_ACTIVE_ARCH=NO \ - CI=TRUE \ - VERSION_NUMBER=${{ inputs.version }} \ - SWIFT_OBJC_INTEROP_MODE=${{ (inputs.cxxInterop && 'objcxx') || 'objc' }} \ - | xcbeautify - - name: Package the XCArchive # To preserve symlinks within the XCArchives that are not preserved by the GitHub Actions artifact upload - run: | - cd .build - tar -zcvf ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz - path: ./.build/${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz + - uses: actions/checkout@v4 + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - name: Check environment + run: | + xcodebuild -version + swift --version + echo Release version: ${{ inputs.version }} + echo SDK: ${{ matrix.sdk }} + - name: Install xcbeautify + if: ${{ !env.selfhosted && inputs.scheme != '' }} + run: brew install xcbeautify + - name: Archive for ${{ matrix.sdk }} SDK + run: | + xcodebuild archive \ + -workspace ${{ inputs.workspaceFile }} \ + -scheme ${{ inputs.scheme }} \ + -configuration ${{ inputs.configuration }} \ + -sdk ${{ matrix.sdk }} \ + -archivePath './.build/${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive' \ + SKIP_INSTALL=NO \ + BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ + ONLY_ACTIVE_ARCH=NO \ + CI=TRUE \ + VERSION_NUMBER=${{ inputs.version }} \ + SWIFT_OBJC_INTEROP_MODE=${{ (inputs.cxxInterop && 'objcxx') || 'objc' }} \ + | xcbeautify + - name: Package the XCArchive # To preserve symlinks within the XCArchives that are not preserved by the GitHub Actions artifact upload + run: | + cd .build + tar -zcvf ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz + path: ./.build/${{ inputs.xcArchiveName }}-${{ matrix.sdk }}.xcarchive.tar.gz diff --git a/.github/workflows/create-and-upload-coverage-report.yml b/.github/workflows/create-and-upload-coverage-report.yml index 625ffb0..667cf8f 100644 --- a/.github/workflows/create-and-upload-coverage-report.yml +++ b/.github/workflows/create-and-upload-coverage-report.yml @@ -12,7 +12,9 @@ on: workflow_call: inputs: coveragereports: - description: 'A string containing all names of the .xcresult files that are downloaded from the artifacts of previous jobs separated by a space character.' + description: | + A string containing all names of the .xcresult files that are downloaded from the artifacts of previous jobs. + Multiple values are separated by a space character. required: true type: string secrets: @@ -25,28 +27,28 @@ jobs: name: Create and upload coverage report runs-on: macos-14 steps: - - uses: actions/checkout@v4 - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - name: Check environment - run: | - xcodebuild -version - swift --version - - uses: actions/download-artifact@v4 - - name: Rename single code coverage report - if: "!contains(inputs.coveragereports, ' ')" - run: | - mv ${{ inputs.coveragereports }} CodeCoverage.xcresult - - name: Merge coverage reports - if: "contains(inputs.coveragereports, ' ')" - run: | - xcrun xcresulttool merge ${{ inputs.coveragereports }} --output-path CodeCoverage.xcresult - rm -rf ${{ inputs.coveragereports }} - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - with: - fail_ci_if_error: true - token: ${{ secrets.token }} - xcode: true - xcode_archive_path: CodeCoverage.xcresult + - uses: actions/checkout@v4 + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - name: Check environment + run: | + xcodebuild -version + swift --version + - uses: actions/download-artifact@v4 + - name: Rename single code coverage report + if: "!contains(inputs.coveragereports, ' ')" + run: | + mv ${{ inputs.coveragereports }} CodeCoverage.xcresult + - name: Merge coverage reports + if: "contains(inputs.coveragereports, ' ')" + run: | + xcrun xcresulttool merge ${{ inputs.coveragereports }} --output-path CodeCoverage.xcresult + rm -rf ${{ inputs.coveragereports }} + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + fail_ci_if_error: true + token: ${{ secrets.token }} + xcode: true + xcode_archive_path: CodeCoverage.xcresult diff --git a/.github/workflows/docc-github-pages.yml b/.github/workflows/docc-github-pages.yml index da236e0..2263035 100644 --- a/.github/workflows/docc-github-pages.yml +++ b/.github/workflows/docc-github-pages.yml @@ -12,31 +12,39 @@ on: workflow_call: inputs: path: - description: 'The path where the project is located. Defaults to $GITHUB_WORKSPACE' + description: | + The path where the project is located. Defaults to $GITHUB_WORKSPACE required: false type: string default: '.' runsonlabels: - description: 'JSON-based collection of labels indicating which type of github runner should be chosen' + description: | + JSON-based collection of labels indicating which type of github runner should be chosen required: false type: string default: '["macos-14"]' xcodeversion: - description: 'The Xcode version used for the build' + description: | + The Xcode version used for the build required: false type: string default: 'latest-stable' scheme: - description: 'The scheme in the Xcode project. Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`' + description: | + The scheme in the Xcode project. + Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`' required: true type: string destination: - description: 'The destination parameter that should be passed to xcodebuild. Defaults to the iOS simulator using an iPhone 15 Pro' + description: | + The destination parameter that should be passed to xcodebuild. + Defaults to the iOS simulator using an iPhone 15 Pro. required: false type: string default: 'platform=iOS Simulator,name=iPhone 15 Pro' dryrun: - description: 'Dry run deployment, only build documentation but do not publish' + description: | + Dry run deployment, only build documentation but do not publish required: false type: boolean default: false diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml index 49f392a..cb5aa8c 100644 --- a/.github/workflows/docker-build-and-push.yml +++ b/.github/workflows/docker-build-and-push.yml @@ -15,35 +15,45 @@ on: workflow_call: inputs: dockerFile: - description: 'Path or name of the Docker file. The default values is `Dockerfile`. The docker file can use the `baseimage` to get an architecture specific Swift base image' + description: | + Path or name of the Docker file. The default values is `Dockerfile`. + The docker file can use the `baseimage` to get an architecture specific Swift base image. required: false type: string default: 'Dockerfile' imageName: - description: 'The name used to tag the docker image on the defined registry containing the organzation/account name and the name of the image, e.g.: stanfordbdhg/example' + description: | + The name used to tag the docker image on the defined registry containing the organzation/account name and the name of the image. + An example would be: stanfordbdhg/example. required: true type: string registry: - description: 'Server address of Docker registry. If not set then will default to ghcr.io' + description: | + Server address of Docker registry. If not set then will default to ghcr.io. required: false type: string default: 'ghcr.io' workingDirectory: - description: 'The working-directory of the GitHub Action. Defaults to $GITHUB_WORKSPACE' + description: | + The working-directory of the GitHub Action. Defaults to $GITHUB_WORKSPACE'. required: false type: string default: '.' environment: - description: 'GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment' + description: | + GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules. + https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment required: false type: string default: '' secrets: username: - description: 'Username for authenticating to the Docker registry. Uses the GitHub actor by default.' + description: | + Username for authenticating to the Docker registry. Uses the GitHub actor by default. required: false password: - description: 'Password or personal access token for authenticating the Docker registry. Uses the GitHub token by default.' + description: | + Password or personal access token for authenticating the Docker registry. Uses the GitHub token by default. required: false permissions: diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index b730f12..79f6bf4 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -24,8 +24,6 @@ permissions: jobs: eslint: runs-on: ubuntu-latest - env: - CI: TRUE steps: - uses: actions/checkout@v4 - name: Setup Node diff --git a/.github/workflows/firebase-deploy.yml b/.github/workflows/firebase-deploy.yml index b493602..ada63e5 100644 --- a/.github/workflows/firebase-deploy.yml +++ b/.github/workflows/firebase-deploy.yml @@ -12,28 +12,36 @@ on: workflow_call: inputs: path: - description: 'The path where the project is located. Defaults to $GITHUB_WORKSPACE' + description: | + The path where the project is located. Defaults to $GITHUB_WORKSPACE. required: false type: string default: '.' customcommand: - description: 'Custom command to be executed before the deployment. Can be used to, e.g., install dependencies for cloud functions.' + description: | + Custom command to be executed before the deployment. Can be used to, e.g., install dependencies for cloud functions. required: false type: string default: '' arguments: - description: 'Arguments passed to the firebase deploy command' + description: | + Arguments passed to the firebase deploy command. required: false type: string default: '' environment: - description: 'GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment' + description: | + GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules. + https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment' required: false type: string default: '' secrets: GOOGLE_APPLICATION_CREDENTIALS_BASE64: - description: 'The Base64 version of the private key JSON file for the service account. You can lean more about how to generate the JSON at https://cloud.google.com/iam/docs/service-accounts-create. The service account must have the minimally required permissions documented at https://firebase.google.com/docs/projects/iam/permissions.' + description: | + The Base64 version of the private key JSON file for the service account. + You can lean more about how to generate the JSON at https://cloud.google.com/iam/docs/service-accounts-create. + The service account must have the minimally required permissions documented at https://firebase.google.com/docs/projects/iam/permissions. required: true jobs: @@ -45,30 +53,30 @@ jobs: working-directory: ${{ inputs.path }} environment: ${{ inputs.environment }} steps: - - name: Check environment - run: | - echo "env.selfhosted: ${{ env.selfhosted }}" - echo "environment: ${{ inputs.environment }}" - - uses: actions/checkout@v4 - - name: Setup NodeJS - uses: actions/setup-node@v3 - - name: Setup Java - uses: actions/setup-java@v3 - with: - distribution: 'microsoft' - java-version: '17' - - name: Install Firebase CLI Tools - run: npm install -g firebase-tools - - name: Run custom command - if: ${{ inputs.customcommand != '' }} - run: ${{ inputs.customcommand }} - - name: Deploy to Firebase - run: | - echo -n "${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}" | base64 -d > "$RUNNER_TEMP/google-application-credentials.json" - export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/google-application-credentials.json" - echo "Stored the Google application credentials at $GOOGLE_APPLICATION_CREDENTIALS" - firebase deploy ${{ inputs.arguments }} - - name: Clean up Google application credentials - if: always() - run: | - rm -rf $RUNNER_TEMP/google-application-credentials.json || true + - name: Check environment + run: | + echo "env.selfhosted: ${{ env.selfhosted }}" + echo "environment: ${{ inputs.environment }}" + - uses: actions/checkout@v4 + - name: Setup NodeJS + uses: actions/setup-node@v3 + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'microsoft' + java-version: '17' + - name: Install Firebase CLI Tools + run: npm install -g firebase-tools + - name: Run custom command + if: ${{ inputs.customcommand != '' }} + run: ${{ inputs.customcommand }} + - name: Deploy to Firebase + run: | + echo -n "${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}" | base64 -d > "$RUNNER_TEMP/google-application-credentials.json" + export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/google-application-credentials.json" + echo "Stored the Google application credentials at $GOOGLE_APPLICATION_CREDENTIALS" + firebase deploy ${{ inputs.arguments }} + - name: Clean up Google application credentials + if: always() + run: | + rm -rf $RUNNER_TEMP/google-application-credentials.json || true diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml index ec4b4e4..8ae42bc 100644 --- a/.github/workflows/markdown-link-check.yml +++ b/.github/workflows/markdown-link-check.yml @@ -15,6 +15,6 @@ jobs: markdown_link_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Markdown Link Check - uses: gaurav-nelson/github-action-markdown-link-check@v1 + - uses: actions/checkout@v3 + - name: Markdown Link Check + uses: gaurav-nelson/github-action-markdown-link-check@v1 diff --git a/.github/workflows/nextjs-github-pages.yml b/.github/workflows/nextjs-github-pages.yml index deb2b01..c1f8715 100644 --- a/.github/workflows/nextjs-github-pages.yml +++ b/.github/workflows/nextjs-github-pages.yml @@ -39,8 +39,6 @@ jobs: cache: 'npm' - name: Install Node Dependencies run: npm ci - env: - CI: TRUE - name: Build & Export with Next.js run: npm run build env: diff --git a/.github/workflows/npm-test-and-coverage.yml b/.github/workflows/npm-test-and-coverage.yml index 7784de5..714c163 100644 --- a/.github/workflows/npm-test-and-coverage.yml +++ b/.github/workflows/npm-test-and-coverage.yml @@ -12,19 +12,32 @@ on: workflow_call: inputs: nodeVersion: - description: 'Node version spec of the version to use in SemVer notation.' + description: | + Node version spec of the version to use in SemVer notation. required: false type: string default: '18' working-directory: - description: 'The working directory where the project is located. Defaults to $GITHUB_WORKSPACE' + description: | + The working directory where the project is located. Defaults to $GITHUB_WORKSPACE. required: false type: string default: '.' + setup-firebase-emulator: + description: | + Setup the Firebase Emulator. + required: false + type: boolean + default: false secrets: token: description: 'The CodeCov token used for private repositories' required: false + GOOGLE_APPLICATION_CREDENTIALS_BASE64: + description: | + The Base64 version of the private key JSON file to boot up the firebase emulator. + Only needed if cloud functions are used to fully support the execution of cloud functions in the emulator. + required: false jobs: testandcoverage: @@ -34,18 +47,50 @@ jobs: working-directory: ${{ inputs.working-directory }} steps: - uses: actions/checkout@v4 + - name: Check environment + run: | + echo "env.selfhosted: ${{ env.selfhosted }}" - name: Setup Node uses: actions/setup-node@v4 with: node-version: ${{ inputs.nodeVersion }} cache: 'npm' + cache-dependency-path: '${{ inputs.working-directory }}/package-lock.json' + - name: Cache Firebase Emulators + if: ${{ !env.selfhosted && inputs.setup-firebase-emulator }} + uses: actions/cache@v4 + with: + path: ~/.cache/firebase/emulators + key: ${{ runner.os }}-${{ runner.arch }}-firebase-emulators-${{ hashFiles('~/.cache/firebase/emulators/**') }} + - name: Setup Java + if: ${{ !env.selfhosted && inputs.setup-firebase-emulator }} + uses: actions/setup-java@v4 + with: + distribution: 'microsoft' + java-version: '17' + - name: Install Firebase CLI Tools + if: ${{ !env.selfhosted && inputs.setup-firebase-emulator }} + run: npm install -g firebase-tools - name: Install Node Dependencies run: npm ci - env: - CI: TRUE - name: Run the tests - run: npm test + run: | + if ${{ inputs.setup-firebase-emulator }}; then + echo -n "${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}" | base64 -d > "$RUNNER_TEMP/google-application-credentials.json" + export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/google-application-credentials.json" + echo "Stored the Google application credentials at $GOOGLE_APPLICATION_CREDENTIALS" + fi + + npm test + env: + GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }} - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 + if: ${{ always() }} with: token: ${{ secrets.token }} + working-directory: ${{ inputs.working-directory }} + - name: Clean up Google application credentials + if: ${{ always() }} + run: | + rm -rf $RUNNER_TEMP/google-application-credentials.json || true diff --git a/.github/workflows/periphery.yml b/.github/workflows/periphery.yml index 2128ad4..a1cae4f 100644 --- a/.github/workflows/periphery.yml +++ b/.github/workflows/periphery.yml @@ -39,19 +39,19 @@ jobs: working-directory: ${{ inputs.path }} environment: ${{ inputs.environment }} steps: - - uses: actions/checkout@v4 - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{ inputs.xcodeversion }} - - name: Check environment - run: | - xcodebuild -version - swift --version - echo "env.selfhosted: ${{ env.selfhosted }}" - echo "environment: ${{ inputs.environment }}" - - name: Install periphery - if: ${{ !env.selfhosted }} - run: brew install peripheryapp/periphery/periphery - - name: Run periphery - run: | - periphery scan --relative-results --format github-actions --strict -- -skipPackagePluginValidation -skipMacroValidation + - uses: actions/checkout@v4 + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{ inputs.xcodeversion }} + - name: Check environment + run: | + xcodebuild -version + swift --version + echo "env.selfhosted: ${{ env.selfhosted }}" + echo "environment: ${{ inputs.environment }}" + - name: Install periphery + if: ${{ !env.selfhosted }} + run: brew install peripheryapp/periphery/periphery + - name: Run periphery + run: | + periphery scan --relative-results --format github-actions --strict -- -skipPackagePluginValidation -skipMacroValidation diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 36d795e..95f448f 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -15,7 +15,7 @@ jobs: reuse: name: REUSE Compliance Check runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: REUSE Compliance Check - uses: fsfe/reuse-action@v1 + steps: + - uses: actions/checkout@v4 + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f4df7e..0752f53 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,3 +22,15 @@ jobs: markdown_link_check: name: Markdown Link Check uses: ./.github/workflows/markdown-link-check.yml + yamllint: + name: YAML Lint Check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + - name: Install yamllint + run: pip install yamllint + - name: Run yamllint with custom config + run: yamllint -c .yamllint.yml . diff --git a/.github/workflows/xcframework-commit-and-release.yml b/.github/workflows/xcframework-commit-and-release.yml index 65900ea..af4ce7c 100644 --- a/.github/workflows/xcframework-commit-and-release.yml +++ b/.github/workflows/xcframework-commit-and-release.yml @@ -12,72 +12,77 @@ on: workflow_call: inputs: dryrun: - description: 'If true, the workflow will not commit and release the built XCFramework.' + description: | + If true, the workflow will not commit and release the built XCFramework. type: boolean required: false default: false outputpath: - description: 'Optional Prefix for the output path' + description: | + Optional Prefix for the output path. type: string required: false default: '.' user: - description: 'Optional GitHub username that is associated with the GitHub Personal Access Token (PAT)' + description: | + Optional GitHub username that is associated with the GitHub Personal Access Token (PAT). type: string required: false default: '' secrets: access-token: - description: 'GitHub Personal Access Token (PAT) if the to-be-committed-to branch is protected and needs a specific access token to push commits to the branch' + description: | + GitHub Personal Access Token (PAT). + Needed if the to-be-committed-to branch is protected and needs a specific access token to push commits to the branch. required: false - + jobs: xcframework-commit-and-release: name: Commit and Release XCFrameworks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.access-token || github.token }} - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - path: ./.build - merge-multiple: true - - name: Untar XCFrameworks - run: | - if ! grep -qxF '.build' .gitignore; then - echo '.build' >> .gitignore - fi - - mkdir -p ${{ inputs.outputpath }} - - find ./.build -name "*.tar.gz" -exec tar -zxvf {} -C ./.build \; - for xcframework in $(find ./.build -name "*.xcframework"); do - rm -rf ${{ inputs.outputpath }}/$(basename "$xcframework") - mv "$xcframework" ${{ inputs.outputpath }} - done - - name: Dry Run - if: ${{ inputs.dryrun }} - run: | - git add ${{ inputs.outputpath }}/*.xcframework - git status - - name: Commit and push XCFrameworks - if: ${{ !inputs.dryrun }} - uses: EndBug/add-and-commit@v9 - with: - message: Create XCFrameworks for release ${{ inputs.version }} - tag: ${{ inputs.version }} --force - tag_push: --force - github_token: ${{ secrets.access-token || github.token }} - author_name: ${{ inputs.user || github.actor }} - author_email: ${{ inputs.user || github.actor }}@users.noreply.github.com - - name: Create Release - uses: softprops/action-gh-release@v1 - if: ${{ !inputs.dryrun }} - with: - tag_name: ${{ inputs.version }} - generate_release_notes: true - fail_on_unmatched_files: true - files: | - ./.build/*.xcframework.tar.gz + - uses: actions/checkout@v4 + with: + token: ${{ secrets.access-token || github.token }} + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + path: ./.build + merge-multiple: true + - name: Untar XCFrameworks + run: | + if ! grep -qxF '.build' .gitignore; then + echo '.build' >> .gitignore + fi + + mkdir -p ${{ inputs.outputpath }} + + find ./.build -name "*.tar.gz" -exec tar -zxvf {} -C ./.build \; + for xcframework in $(find ./.build -name "*.xcframework"); do + rm -rf ${{ inputs.outputpath }}/$(basename "$xcframework") + mv "$xcframework" ${{ inputs.outputpath }} + done + - name: Dry Run + if: ${{ inputs.dryrun }} + run: | + git add ${{ inputs.outputpath }}/*.xcframework + git status + - name: Commit and push XCFrameworks + if: ${{ !inputs.dryrun }} + uses: EndBug/add-and-commit@v9 + with: + message: Create XCFrameworks for release ${{ inputs.version }} + tag: ${{ inputs.version }} --force + tag_push: --force + github_token: ${{ secrets.access-token || github.token }} + author_name: ${{ inputs.user || github.actor }} + author_email: ${{ inputs.user || github.actor }}@users.noreply.github.com + - name: Create Release + uses: softprops/action-gh-release@v1 + if: ${{ !inputs.dryrun }} + with: + tag_name: ${{ inputs.version }} + generate_release_notes: true + fail_on_unmatched_files: true + files: | + ./.build/*.xcframework.tar.gz diff --git a/.github/workflows/xcframework.yml b/.github/workflows/xcframework.yml index d019b23..79ad1c9 100644 --- a/.github/workflows/xcframework.yml +++ b/.github/workflows/xcframework.yml @@ -12,34 +12,44 @@ on: workflow_call: inputs: workspaceFile: - description: 'The path of the Xcode Workspace file (including the file extension).' + description: | + The path of the Xcode Workspace file (including the file extension). type: string required: true xcFrameworkName: - description: 'The name of the to be created XCFramework. It must not include the default XCFramework extension ".xcframework" as the file naming is automatically done be the workflow.' + description: | + The name of the to be created XCFramework. + It must not include the default XCFramework extension ".xcframework" as the file naming is automatically done be the workflow. type: string required: true scheme: - description: 'The project scheme that should be used for the archiving process.' + description: | + The project scheme that should be used for the archiving process. type: string required: true version: - description: 'The version number of the XCFramework embedded in the XCArchives. This version number is also used for the release tag.' + description: | + The version number of the XCFramework embedded in the XCArchives. + This version number is also used for the release tag. type: string required: false default: 'ci' configuration: - description: 'The build configuration to use when archiving the scheme, either Debug or Release.' + description: | + The build configuration to use when archiving the scheme, either Debug or Release. type: string required: false default: 'Release' runsonlabels: - description: 'JSON-based collection of labels indicating which type of github runner should be chosen.' + description: | + JSON-based collection of labels indicating which type of github runner should be chosen. type: string required: false default: '["macos-14"]' sdk: - description: 'JSON-based collection of SDK for the exported framework. Defaults to all SDKs. You can list SDKs using `xcodebuild -showsdks`.' + description: | + JSON-based collection of SDK for the exported framework. + Defaults to all SDKs. You can list SDKs using `xcodebuild -showsdks`. type: string required: false default: '["iphoneos", "iphonesimulator", "macosx", "appletvos", "appletvsimulator", "xros", "xrsimulator", "watchos", "watchsimulator"]' @@ -49,13 +59,15 @@ on: required: false default: '.' user: - description: 'Optional GitHub username that is associated with the GitHub Personal Access Token (PAT)' + description: | + Optional GitHub username that is associated with the GitHub Personal Access Token (PAT). type: string required: false default: '' secrets: access-token: - description: 'GitHub Personal Access Token (PAT) if the to-be-commited-to branch is protected and needs a specific access token to push commits to the branch' + description: | + GitHub Personal Access Token (PAT) if the to-be-commited-to branch is protected and needs a specific access token to push to the branch. required: false jobs: @@ -75,58 +87,62 @@ jobs: runs-on: ${{ fromJson(inputs.runsonlabels) }} needs: build-xcarchive steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.access-token || github.token }} - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - name: Check environment - run: | - xcodebuild -version - swift --version - echo Release version: ${{ inputs.version }} - - uses: actions/download-artifact@v4 - with: - path: ./.build - merge-multiple: true - - name: Unpack XCArchives and create XCFramework - run: | - rm -rf ${{ inputs.xcFrameworkName }}.xcframework - - # Convert JSON array to space-separated string - SDK_LIST="${{ inputs.sdk }}" - SDK_LIST="${SDK_LIST//[\[\]\",]/}" # Remove JSON characters - echo "Parsed SDK list: $SDK_LIST" - - IFS=' ' read -r -a SDKS <<< "$SDK_LIST" - FRAMEWORKS_ARGS="" - for SDK in "${SDKS[@]}"; do - # Unpack the XCArchive - tar -zxvf ./.build/${{ inputs.xcFrameworkName }}-${SDK}.xcarchive.tar.gz -C ./.build/ - # Specify the path to the framework within the XCArchive - ARCHIVE_PATH="./.build/${{ inputs.xcFrameworkName }}-${SDK}.xcarchive/Products/Library/Frameworks/${{ inputs.xcFrameworkName }}.framework" - echo "Checking archive path: $ARCHIVE_PATH" - if [ -d "$ARCHIVE_PATH" ]; then - FRAMEWORKS_ARGS+="-framework $ARCHIVE_PATH " - echo "Archive path valid: $ARCHIVE_PATH" - else - echo "Warning: Archive path for SDK $SDK does not exist: $ARCHIVE_PATH" - fi - done - - # Trim trailing space - FRAMEWORKS_ARGS=$(echo "$FRAMEWORKS_ARGS" | xargs) - - echo "Executing xcodebuild with args: $FRAMEWORKS_ARGS" - xcodebuild -create-xcframework $FRAMEWORKS_ARGS -output ${{ inputs.xcFrameworkName }}.xcframework | xcbeautify || { echo "xcodebuild failed"; exit 1; } - - rm -rf .build - - name: Create Artifacts - run: | - tar -zcvf ${{ inputs.xcFrameworkName }}.xcframework.tar.gz ${{ inputs.xcFrameworkName }}.xcframework - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.xcFrameworkName }}.xcframework.tar.gz - path: ${{ inputs.xcFrameworkName }}.xcframework.tar.gz + - uses: actions/checkout@v4 + with: + token: ${{ secrets.access-token || github.token }} + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + - name: Check environment + run: | + xcodebuild -version + swift --version + echo Release version: ${{ inputs.version }} + - uses: actions/download-artifact@v4 + with: + path: ./.build + merge-multiple: true + - name: Unpack XCArchives and create XCFramework + run: | + rm -rf ${{ inputs.xcFrameworkName }}.xcframework + + # Convert JSON array to space-separated string + SDK_LIST="${{ inputs.sdk }}" + SDK_LIST="${SDK_LIST//[\[\]\",]/}" # Remove JSON characters + echo "Parsed SDK list: $SDK_LIST" + + IFS=' ' read -r -a SDKS <<< "$SDK_LIST" + FRAMEWORKS_ARGS="" + for SDK in "${SDKS[@]}"; do + # Unpack the XCArchive + tar -zxvf ./.build/${{ inputs.xcFrameworkName }}-${SDK}.xcarchive.tar.gz -C ./.build/ + # Specify the path to the framework within the XCArchive + ARCHIVE="./.build/${{ inputs.xcFrameworkName }}-${SDK}.xcarchive/Products/Library/Frameworks/${{ inputs.xcFrameworkName }}.framework" + echo "Checking archive path: $ARCHIVE" + if [ -d "$ARCHIVE" ]; then + FRAMEWORKS_ARGS+="-framework $ARCHIVE " + echo "Archive path valid: $ARCHIVE" + else + echo "Warning: Archive path for SDK $SDK does not exist: $ARCHIVE" + fi + done + + # Trim trailing space + FRAMEWORKS_ARGS=$(echo "$FRAMEWORKS_ARGS" | xargs) + + echo "Executing xcodebuild with args: $FRAMEWORKS_ARGS" + xcodebuild \ + -create-xcframework $FRAMEWORKS_ARGS \ + -output ${{ inputs.xcFrameworkName }}.xcframework \ + | xcbeautify \ + || { echo "xcodebuild failed"; exit 1; } + + rm -rf .build + - name: Create Artifacts + run: | + tar -zcvf ${{ inputs.xcFrameworkName }}.xcframework.tar.gz ${{ inputs.xcFrameworkName }}.xcframework + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.xcFrameworkName }}.xcframework.tar.gz + path: ${{ inputs.xcFrameworkName }}.xcframework.tar.gz diff --git a/.github/workflows/xcodebuild-or-fastlane.yml b/.github/workflows/xcodebuild-or-fastlane.yml index 998b9a4..0585c72 100644 --- a/.github/workflows/xcodebuild-or-fastlane.yml +++ b/.github/workflows/xcodebuild-or-fastlane.yml @@ -12,140 +12,185 @@ on: workflow_call: inputs: path: - description: 'The path where the project is located. Defaults to $GITHUB_WORKSPACE' + description: | + The path where the project is located. Defaults to $GITHUB_WORKSPACE. required: false type: string default: '.' runsonlabels: - description: 'JSON-based collection of labels indicating which type of github runner should be chosen' + description: | + JSON-based collection of labels indicating which type of github runner should be chosen. required: false type: string default: '["macos-14"]' xcodeversion: - description: 'The Xcode version used for the build' + description: | + The Xcode version used for the build. required: false type: string default: 'latest-stable' scheme: - description: 'The scheme in the Xcode project. Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`' + description: | + The scheme in the Xcode project. + Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`. required: false type: string default: '' buildConfig: - description: 'The build configuration parameter that should be passed to xcodebuild. Either use `Debug` or `Release` to build in the respective modes. If not defined, the `Debug` configuration is used.' + description: | + The build configuration parameter that should be passed to xcodebuild. + Either use `Debug` or `Release` to build in the respective modes. + If not defined, the `Debug` configuration is used. required: false type: string default: 'Debug' destination: - description: 'The destination parameter that should be passed to xcodebuild. Defaults to the iOS simulator using an iPhone 15 Pro' + description: | + The destination parameter that should be passed to xcodebuild. + Defaults to the iOS simulator using an iPhone 15 Pro. required: false type: string default: 'platform=iOS Simulator,name=iPhone 15 Pro' setupSimulators: - description: 'Flag indicating if all iOS simulators matching the `destination` input shoud be setup (e.g. password autofill functionality should be disabled).' + description: | + Flag indicating if all iOS simulators matching the `destination` input shoud be setup. + Includes, e.g., password autofill functionality should be disabled. required: false type: boolean default: false resultBundle: - description: 'The name of the Xcode result bundle that is passed to xcodebuild. If not defined, the name of the scheme + .xcresult is used.' + description: | + The name of the Xcode result bundle that is passed to xcodebuild. + If not defined, the name of the scheme + .xcresult is used.' required: false type: string default: '' test: - description: 'A flag indicating if the tests of the Xcode project scheme should run' + description: | + A flag indicating if the tests of the Xcode project scheme should run. required: false type: boolean default: true fastlanelane: - description: 'The lane of the fastlane command. Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`' + description: | + The lane of the fastlane command. + Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`. required: false type: string default: '' customcommand: - description: 'A custom command that should be run after the setup. Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`' + description: | + A custom command that should be run after the setup. + Either use `scheme` to use xcodebuild, `fastlanelane` to use fastlane, or a custom command using `customcommand`. required: false type: string default: '' artifactname: - description: 'The name & path of the artifact that should be uploaded at the end of the build.' + description: | + The name & path of the artifact that should be uploaded at the end of the build. required: false type: string default: '' environment: - description: 'GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment' + description: | + GitHub deployment environment to optionally adjust access to variables and secrets with additional protection rules. + https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment required: false type: string default: '' setupsigning: - description: 'Setup the keychain to include Apple certificate and provisioning profile' + description: | + Setup the keychain to include Apple certificate and provisioning profile. required: false type: boolean default: false cacheDerivedData: - description: 'Cache the derived data folder for a build using xcodebuild' + description: | + Cache the derived data folder for a build using xcodebuild. required: false type: boolean default: false setupfirebaseemulator: - description: 'Setup the Firebase Emulator & automatically use it for the automated fastlane commands.' + description: | + Setup the Firebase Emulator & automatically use it for the automated fastlane commands. required: false type: boolean default: false firebaseemulatorimport: - description: 'Firebase import directory that contains Authentication, Cloud Firestore, Realtime Database and Cloud Storage data for Firebase emulators to use as a shareable, common baseline data set.' + description: | + Firebase import directory that contains Authentication, Cloud Firestore, Realtime Database and Cloud Storage data for Firebase emulators. + Can be used to inject a shareable, common baseline data set. required: false type: string default: '' googleserviceinfoplistpath: - description: 'Path to the GoogleService-Info.plist file that is replaced using the content found in the secret GOOGLE_SERVICE_INFO_PLIST' + description: | + Path to the GoogleService-Info.plist file that is replaced using the content found in the secret GOOGLE_SERVICE_INFO_PLIST. required: false type: string default: '' codeql: - description: 'Use CodeQL code scanning' + description: | + Use CodeQL code scanning. required: false type: boolean default: false checkout_submodules: - description: "Flag indicating if submodules should be automatically checked out." + description: | + Flag indicating if submodules should be automatically checked out. required: false type: boolean secrets: BUILD_CERTIFICATE_BASE64: - description: 'The Base64 version of the Apple signing certificate to build your iOS application.' + description: | + The Base64 version of the Apple signing certificate to build your iOS application. required: false P12_PASSWORD: - description: 'The password for the Apple signing certificate.' + description: | + The password for the Apple signing certificate. required: false BUILD_PROVISION_PROFILE_BASE64: - description: 'The Base64 version of the Apple provisioning profile to build your main application (e.g. iOS app).' + description: | + The Base64 version of the Apple provisioning profile to build your main application (e.g. iOS app). required: false BUILD_SECONDARY_PROVISION_PROFILE_BASE64: - description: 'The Base64 version of the Apple provisioning profile to build your an accompanying application (e.g. watchOS app).' + description: | + The Base64 version of the Apple provisioning profile to build your an accompanying application (e.g. watchOS app). required: false KEYCHAIN_PASSWORD: - description: 'A password for the keychain that will be created on the runner instance.' + description: | + A password for the keychain that will be created on the runner instance. required: false APP_STORE_CONNECT_API_KEY_ID: - description: 'The key ID of the API key created in the App Store Connect API keys section.' + description: | + The key ID of the API key created in the App Store Connect API keys section. required: false APP_STORE_CONNECT_ISSUER_ID: - description: 'The issuer ID of the App Store Connect API is displayed in the App Store Connect API keys section.' + description: | + The issuer ID of the App Store Connect API is displayed in the App Store Connect API keys section. required: false APP_STORE_CONNECT_API_KEY_BASE64: - description: 'The content of the key created in App Store Connect condensed into a Base64 representation, e.g., using base64 -i AuthKey_ABCDEFGHIJ.p8 | pbcopy.' + description: | + The content of the key created in App Store Connect condensed into a Base64 representation. + Can be generated using, e.g., `$ base64 -i AuthKey_ABCDEFGHIJ.p8 | pbcopy`. required: false APPLE_ID: - description: 'The Apple ID you use to access the App Store Connect API.' + description: | + The Apple ID you use to access the App Store Connect API. required: false CHECKOUT_TOKEN: - description: 'The Personal access token (PAT) to use with the checkout action' + description: | + The Personal access token (PAT) to use with the checkout action. required: false GOOGLE_SERVICE_INFO_PLIST_BASE64: - description: 'The Base64 version of the GoogleService-Info.plist file that is used to replace the file found at googleserviceinfoplistpath if the arguemnt is set.' + description: | + The Base64 version of the GoogleService-Info.plist file that is used. + Replace the file found at googleserviceinfoplistpath if the arguemnt is set. required: false GOOGLE_APPLICATION_CREDENTIALS_BASE64: - description: 'The Base64 version of the private key JSON file to boot up the firebase emulator to fully support the execution of cloud functions in the emulator. Only needed if cloud functions are used.' + description: | + The Base64 version of the private key JSON file to boot up the firebase emulator. + Only needed if cloud functions are used to fully support the execution of cloud functions in the emulator. required: false jobs: @@ -157,271 +202,273 @@ jobs: working-directory: ${{ inputs.path }} environment: ${{ inputs.environment }} steps: - - uses: actions/checkout@v4 - with: - # This is GitHubs way of implementing ternary expressions (see https://docs.github.com/en/actions/learn-github-actions/expressions) - token: ${{ secrets.CHECKOUT_TOKEN != '' && secrets.CHECKOUT_TOKEN || github.token }} - submodules: ${{ inputs.checkout_submodules }} - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{ inputs.xcodeversion }} - - name: Check environment - run: | - xcodebuild -version - swift --version - echo "env.selfhosted: ${{ env.selfhosted }}" - echo "environment: ${{ inputs.environment }}" - - name: Install xcbeautify - if: ${{ !env.selfhosted && inputs.scheme != '' }} - run: brew install xcbeautify - - name: Cache .derivedData folder - if: ${{ inputs.cacheDerivedData }} - uses: actions/cache@v4 - with: - path: .derivedData - key: ${{ runner.os }}-${{ runner.arch }}-derivedData-${{ hashFiles('**/Package.swift', '**/*.pbxproj') }} - restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-derivedData- - - name: Cache Firebase Emulators - if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} - uses: actions/cache@v4 - with: - path: ~/.cache/firebase/emulators - key: ${{ runner.os }}-${{ runner.arch }}-firebase-emulators-${{ hashFiles('~/.cache/firebase/emulators/**') }} - - name: Setup NodeJS - if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} - uses: actions/setup-node@v4 - - name: Setup Java - if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} - uses: actions/setup-java@v4 - with: - distribution: 'microsoft' - java-version: '17' - - name: Install Firebase CLI Tools - if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} - run: npm install -g firebase-tools - - name: Install the Apple certificate and provisioning profile - if: ${{ inputs.setupsigning }} - env: - BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} - P12_PASSWORD: ${{ secrets.P12_PASSWORD }} - BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} - BUILD_SECONDARY_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_SECONDARY_PROVISION_PROFILE_BASE64 }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - run: | - # Create Variables - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + - uses: actions/checkout@v4 + with: + # This is GitHubs way of implementing ternary expressions (see https://docs.github.com/en/actions/learn-github-actions/expressions) + token: ${{ secrets.CHECKOUT_TOKEN != '' && secrets.CHECKOUT_TOKEN || github.token }} + submodules: ${{ inputs.checkout_submodules }} + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{ inputs.xcodeversion }} + - name: Check environment + run: | + xcodebuild -version + swift --version + echo "env.selfhosted: ${{ env.selfhosted }}" + echo "environment: ${{ inputs.environment }}" + - name: Install xcbeautify + if: ${{ !env.selfhosted && inputs.scheme != '' }} + run: brew install xcbeautify + - name: Cache .derivedData folder + if: ${{ inputs.cacheDerivedData }} + uses: actions/cache@v4 + with: + path: .derivedData + key: ${{ runner.os }}-${{ runner.arch }}-derivedData-${{ hashFiles('**/Package.swift', '**/*.pbxproj') }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-derivedData- + - name: Cache Firebase Emulators + if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} + uses: actions/cache@v4 + with: + path: ~/.cache/firebase/emulators + key: ${{ runner.os }}-${{ runner.arch }}-firebase-emulators-${{ hashFiles('~/.cache/firebase/emulators/**') }} + - name: Setup NodeJS + if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} + uses: actions/setup-node@v4 + - name: Setup Java + if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} + uses: actions/setup-java@v4 + with: + distribution: 'microsoft' + java-version: '17' + - name: Install Firebase CLI Tools + if: ${{ !env.selfhosted && inputs.setupfirebaseemulator }} + run: npm install -g firebase-tools + - name: Install the Apple certificate and provisioning profile + if: ${{ inputs.setupsigning }} + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} + P12_PASSWORD: ${{ secrets.P12_PASSWORD }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} + BUILD_SECONDARY_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_SECONDARY_PROVISION_PROFILE_BASE64 }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + # Create Variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - # Import Certificate and Provisioning Profile from Secrets - echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH - echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH + # Import Certificate and Provisioning Profile from Secrets + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH - # Create a Temporary Keychain - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + # Create a Temporary Keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - # Import Certificate to the Keychain - security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH + # Import Certificate to the Keychain + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH - # Apply Provisioning Profile - mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles - UUID=`grep UUID -A1 -a $PP_PATH | grep -io "[-A-F0-9]\{36\}"` - cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/$UUID.mobileprovision + # Apply Provisioning Profile + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + UUID=`grep UUID -A1 -a $PP_PATH | grep -io "[-A-F0-9]\{36\}"` + cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles/$UUID.mobileprovision - # Secondary Provisioning Profile - if [ -n "$BUILD_SECONDARY_PROVISION_PROFILE_BASE64" ]; then - PP_SECONDARY_PATH=$RUNNER_TEMP/build_pp_secondary.mobileprovision - echo -n "$BUILD_SECONDARY_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_SECONDARY_PATH - SECONDARY_UUID=`grep UUID -A1 -a $PP_SECONDARY_PATH | grep -io "[-A-F0-9]\{36\}"` - cp $PP_SECONDARY_PATH ~/Library/MobileDevice/Provisioning\ Profiles/$SECONDARY_UUID.mobileprovision - fi - - name: Setup Google Services File - if: ${{ inputs.googleserviceinfoplistpath != '' }} - run: | - echo -n "${{ secrets.GOOGLE_SERVICE_INFO_PLIST_BASE64 }}" | base64 --decode -o "${{ inputs.googleserviceinfoplistpath }}" - - name: Initialize CodeQL - if: ${{ !env.selfhosted && inputs.codeql }} - uses: github/codeql-action/init@v3 - with: - languages: swift - db-location: '${{ inputs.path }}/.codeql' - - name: Disable Password Autofill in the iOS Simulator - if: ${{ inputs.setupSimulators && inputs.destination != '' }} - run: | - # Function to parse the device name from input string - parse_device_name() { - local input_str=$1 - local IFS=',' # Set Internal Field Separator to comma for splitting - - for kv in $input_str; do - key="${kv%%=*}" # Extract key (everything before '=') - value="${kv#*=}" # Extract value (everything after '=') - - if [ "$key" = "name" ]; then - echo "$value" - return - fi - done - } + # Secondary Provisioning Profile + if [ -n "$BUILD_SECONDARY_PROVISION_PROFILE_BASE64" ]; then + PP_SECONDARY_PATH=$RUNNER_TEMP/build_pp_secondary.mobileprovision + echo -n "$BUILD_SECONDARY_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_SECONDARY_PATH + SECONDARY_UUID=`grep UUID -A1 -a $PP_SECONDARY_PATH | grep -io "[-A-F0-9]\{36\}"` + cp $PP_SECONDARY_PATH ~/Library/MobileDevice/Provisioning\ Profiles/$SECONDARY_UUID.mobileprovision + fi + - name: Setup Google Services File + if: ${{ inputs.googleserviceinfoplistpath != '' }} + run: | + echo -n "${{ secrets.GOOGLE_SERVICE_INFO_PLIST_BASE64 }}" | base64 --decode -o "${{ inputs.googleserviceinfoplistpath }}" + - name: Initialize CodeQL + if: ${{ !env.selfhosted && inputs.codeql }} + uses: github/codeql-action/init@v3 + with: + languages: swift + db-location: '${{ inputs.path }}/.codeql' + - name: Disable Password Autofill in the iOS Simulator + if: ${{ inputs.setupSimulators && inputs.destination != '' }} + run: | + # Function to parse the device name from input string + parse_device_name() { + local input_str=$1 + local IFS=',' # Set Internal Field Separator to comma for splitting - # Extract device name from the input - DEVICE_NAME=$(parse_device_name "${{ inputs.destination }}") + for kv in $input_str; do + key="${kv%%=*}" # Extract key (everything before '=') + value="${kv#*=}" # Extract value (everything after '=') - echo "Device name: $DEVICE_NAME" - - # Retrieve the iOS simulator IDs for the specified device - REGEX_PATTERN="$DEVICE_NAME( Simulator)? \(.*\)" - SIMULATOR_IDS=$(xctrace list devices | grep -E "$REGEX_PATTERN" | awk '{print $NF}' | tr -d '()') + if [ "$key" = "name" ]; then + echo "$value" + return + fi + done + } - # Check if SIMULATOR_IDS is empty - if [ -z "$SIMULATOR_IDS" ]; then - echo "No simulators found for the specified device." - exit 1 - fi + # Extract device name from the input + DEVICE_NAME=$(parse_device_name "${{ inputs.destination }}") - # Loop through each Simulator ID - for SIMULATOR_ID in $SIMULATOR_IDS; do - echo "Processing Simulator ID: $SIMULATOR_ID" + echo "Device name: $DEVICE_NAME" - PLIST1="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist" - PLIST2="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist" - PLIST3="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist" + # Retrieve the iOS simulator IDs for the specified device + REGEX_PATTERN="$DEVICE_NAME( Simulator)? \(.*\)" + SIMULATOR_IDS=$(xctrace list devices | grep -E "$REGEX_PATTERN" | awk '{print $NF}' | tr -d '()') - if [ ! -f "$PLIST1" ] || [ ! -f "$PLIST2" ] || [ ! -f "$PLIST3" ]; then - echo "Simulator $SIMULATOR_ID booting ..." - xcrun simctl boot "$SIMULATOR_ID" - fi + # Check if SIMULATOR_IDS is empty + if [ -z "$SIMULATOR_IDS" ]; then + echo "No simulators found for the specified device." + exit 1 + fi - # Loop for a maximum of 30 seconds - for (( i=0; i<30; i++ )); do - if [ -f "$PLIST1" ] && [ -f "$PLIST2" ] && [ -f "$PLIST3" ]; then - echo "All files found." - break - fi - sleep 1 - done + # Loop through each Simulator ID + for SIMULATOR_ID in $SIMULATOR_IDS; do + echo "Processing Simulator ID: $SIMULATOR_ID" - # Check if the loop exited because all files were found or because of timeout - if [ ! -f "$PLIST1" ] || [ ! -f "$PLIST2" ] || [ ! -f "$PLIST3" ]; then - echo "Error: Not all files were found within the 30-second timeout." - exit 1 - fi + PLIST1="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist" + PLIST2="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist" + PLIST3="$HOME/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist" - sleep 5 + if [ ! -f "$PLIST1" ] || [ ! -f "$PLIST2" ] || [ ! -f "$PLIST3" ]; then + echo "Simulator $SIMULATOR_ID booting ..." + xcrun simctl boot "$SIMULATOR_ID" + fi - # Disable AutoFillPasswords - plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST1 - plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST2 - plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST3 - /usr/libexec/PlistBuddy -c "Add :KeyboardContinuousPathEnabled bool false" /Users/githubaction/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/Preferences/com.apple.keyboard.ContinuousPath.plist + # Loop for a maximum of 30 seconds + for (( i=0; i<30; i++ )); do + if [ -f "$PLIST1" ] && [ -f "$PLIST2" ] && [ -f "$PLIST3" ]; then + echo "All files found." + break + fi + sleep 1 + done - sleep 1 + # Check if the loop exited because all files were found or because of timeout + if [ ! -f "$PLIST1" ] || [ ! -f "$PLIST2" ] || [ ! -f "$PLIST3" ]; then + echo "Error: Not all files were found within the 30-second timeout." + exit 1 + fi + + sleep 5 + + # Disable AutoFillPasswords + plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST1 + plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST2 + plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO $PLIST3 + /usr/libexec/PlistBuddy \ + -c "Add :KeyboardContinuousPathEnabled bool false" \ + /Users/githubaction/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/Preferences/com.apple.keyboard.ContinuousPath.plist - # Restart (shutdown if needed and boot) the iOS simulator for the changes to take effect - if xcrun simctl shutdown "$SIMULATOR_ID"; then - echo "Simulator $SIMULATOR_ID shutdown successfully." + sleep 1 + + # Restart (shutdown if needed and boot) the iOS simulator for the changes to take effect + if xcrun simctl shutdown "$SIMULATOR_ID"; then + echo "Simulator $SIMULATOR_ID shutdown successfully." + else + echo "Unable to shutdown simulator $SIMULATOR_ID as it is already shutdown." + fi + done + - name: Run custom command + if: ${{ inputs.customcommand != '' }} + run: ${{ inputs.customcommand }} + env: + APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + APPLE_ID: ${{ secrets.APPLE_ID }} + - name: Resolve dependencies (xcodebuild) + if: ${{ inputs.scheme != '' }} + run: | + xcodebuild \ + -scheme ${{ inputs.scheme }} \ + -resolvePackageDependencies \ + -derivedDataPath ".derivedData" \ + | xcbeautify \ + || true + - name: Build and test (xcodebuild) + if: ${{ inputs.scheme != '' }} + run: | + if ${{ inputs.test }}; then + XCODECOMMAND="test" + CODECOVERAGEFLAG="-enableCodeCoverage YES" else - echo "Unable to shutdown simulator $SIMULATOR_ID as it is already shutdown." + XCODECOMMAND="build" fi - done - - name: Run custom command - if: ${{ inputs.customcommand != '' }} - run: ${{ inputs.customcommand }} - env: - APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} - APPLE_ID: ${{ secrets.APPLE_ID }} - - name: Resolve dependencies (xcodebuild) - if: ${{ inputs.scheme != '' }} - run: | - xcodebuild \ - -scheme ${{ inputs.scheme }} \ - -resolvePackageDependencies \ - -derivedDataPath ".derivedData" \ - | xcbeautify \ - || true - - name: Build and test (xcodebuild) - if: ${{ inputs.scheme != '' }} - run: | - if ${{ inputs.test }}; then - XCODECOMMAND="test" - CODECOVERAGEFLAG="-enableCodeCoverage YES" - else - XCODECOMMAND="build" - fi - if [ -z "${{ inputs.resultBundle }}" ]; then - RESULTBUNDLE=${{ inputs.scheme }}.xcresult - else - RESULTBUNDLE=${{ inputs.resultBundle }} - fi + if [ -z "${{ inputs.resultBundle }}" ]; then + RESULTBUNDLE=${{ inputs.scheme }}.xcresult + else + RESULTBUNDLE=${{ inputs.resultBundle }} + fi - if [ "${{ inputs.buildConfig }}" = "Release" ]; then - ENABLE_TESTING_FLAG="-enable-testing" - else - ENABLE_TESTING_FLAG="" - fi + if [ "${{ inputs.buildConfig }}" = "Release" ]; then + ENABLE_TESTING_FLAG="-enable-testing" + else + ENABLE_TESTING_FLAG="" + fi - set -o pipefail \ - && xcodebuild $XCODECOMMAND \ - -scheme "${{ inputs.scheme }}" \ - -configuration "${{ inputs.buildConfig }}" \ - -destination "${{ inputs.destination }}" \ - $CODECOVERAGEFLAG \ - -derivedDataPath ".derivedData" \ - -resultBundlePath "$RESULTBUNDLE" \ - CODE_SIGNING_REQUIRED=NO \ - CODE_SIGN_IDENTITY="" \ - OTHER_SWIFT_FLAGS="\$(inherited) $ENABLE_TESTING_FLAG" \ - -skipPackagePluginValidation \ - -skipMacroValidation \ - | xcbeautify - - name: Fastlane - if: ${{ inputs.fastlanelane != '' }} - run: | - if ${{ inputs.setupfirebaseemulator }}; then - # We try to do an npm install in the functions directory. - npm --prefix ./functions install || true + set -o pipefail \ + && xcodebuild $XCODECOMMAND \ + -scheme "${{ inputs.scheme }}" \ + -configuration "${{ inputs.buildConfig }}" \ + -destination "${{ inputs.destination }}" \ + $CODECOVERAGEFLAG \ + -derivedDataPath ".derivedData" \ + -resultBundlePath "$RESULTBUNDLE" \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGN_IDENTITY="" \ + OTHER_SWIFT_FLAGS="\$(inherited) $ENABLE_TESTING_FLAG" \ + -skipPackagePluginValidation \ + -skipMacroValidation \ + | xcbeautify + - name: Fastlane + if: ${{ inputs.fastlanelane != '' }} + run: | + if ${{ inputs.setupfirebaseemulator }}; then + # We try to do an npm install in the functions directory. + npm --prefix ./functions install || true - echo -n "${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}" | base64 -d > "$RUNNER_TEMP/google-application-credentials.json" - export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/google-application-credentials.json" - echo "Stored the Google application credentials at $GOOGLE_APPLICATION_CREDENTIALS" + echo -n "${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }}" | base64 -d > "$RUNNER_TEMP/google-application-credentials.json" + export GOOGLE_APPLICATION_CREDENTIALS="$RUNNER_TEMP/google-application-credentials.json" + echo "Stored the Google application credentials at $GOOGLE_APPLICATION_CREDENTIALS" - if [ -n "${{ inputs.firebaseemulatorimport }}" ]; then - echo "Importing firebase emulator data from ${{ inputs.firebaseemulatorimport }}" - firebase emulators:exec --import=${{ inputs.firebaseemulatorimport }} 'fastlane ${{ inputs.fastlanelane }}' - else - firebase emulators:exec 'fastlane ${{ inputs.fastlanelane }}' - fi - else - fastlane ${{ inputs.fastlanelane }} - fi - env: - APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} - APPLE_ID: ${{ secrets.APPLE_ID }} - GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }} - - name: Perform CodeQL Analysis - if: ${{ !env.selfhosted && inputs.codeql }} - uses: github/codeql-action/analyze@v3 - - name: Upload artifact - if: ${{ (success() || failure()) && inputs.artifactname != '' && inputs.buildConfig != 'Release' }} - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.artifactname }} - path: ${{ inputs.path }}/${{ inputs.artifactname }} - - name: Clean up keychain and provisioning profile - if: ${{ (inputs.setupsigning && env.selfhosted) || failure() }} - run: | - security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true - rm -rf ~/Library/MobileDevice/Provisioning\ Profiles || true - - name: Clean up Google application credentials - if: ${{ inputs.fastlanelane != '' || failure() }} - run: | - rm -rf $RUNNER_TEMP/google-application-credentials.json || true \ No newline at end of file + if [ -n "${{ inputs.firebaseemulatorimport }}" ]; then + echo "Importing firebase emulator data from ${{ inputs.firebaseemulatorimport }}" + firebase emulators:exec --import=${{ inputs.firebaseemulatorimport }} 'fastlane ${{ inputs.fastlanelane }}' + else + firebase emulators:exec 'fastlane ${{ inputs.fastlanelane }}' + fi + else + fastlane ${{ inputs.fastlanelane }} + fi + env: + APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }} + APPLE_ID: ${{ secrets.APPLE_ID }} + GOOGLE_APPLICATION_CREDENTIALS_BASE64: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS_BASE64 }} + - name: Perform CodeQL Analysis + if: ${{ !env.selfhosted && inputs.codeql }} + uses: github/codeql-action/analyze@v3 + - name: Upload artifact + if: ${{ (success() || failure()) && inputs.artifactname != '' && inputs.buildConfig != 'Release' }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifactname }} + path: ${{ inputs.path }}/${{ inputs.artifactname }} + - name: Clean up keychain and provisioning profile + if: ${{ (inputs.setupsigning && env.selfhosted) || failure() }} + run: | + security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true + rm -rf ~/Library/MobileDevice/Provisioning\ Profiles || true + - name: Clean up Google application credentials + if: ${{ inputs.fastlanelane != '' || failure() }} + run: | + rm -rf $RUNNER_TEMP/google-application-credentials.json || true diff --git a/.yamllint.yml b/.yamllint.yml new file mode 100644 index 0000000..961cfbf --- /dev/null +++ b/.yamllint.yml @@ -0,0 +1,18 @@ +# +# This source file is part of the Stanford Biodesign Digital Health Group open-source organization +# +# SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md) +# +# SPDX-License-Identifier: MIT +# + +extends: default + +rules: + line-length: + max: 150 + level: warning + truthy: + level: error + allowed-values: ["false", "true", "on"] # On to enable the on: setup for GitHub actions. + document-start: disable diff --git a/FUNDING.yml b/FUNDING.yml index fef7966..65f3aff 100644 --- a/FUNDING.yml +++ b/FUNDING.yml @@ -6,4 +6,4 @@ # SPDX-License-Identifier: MIT # -custom: [Stanford Biodesign Digital Health Group.stanford.edu] \ No newline at end of file +custom: [Stanford Biodesign Digital Health Group.stanford.edu]