diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 001aa3fc4..6c107f99f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,13 +2,26 @@ name: Build on: workflow_call: + secrets: + OAUTH_CLIENT_ID: + required: true + # Signing certificates + CSC_LINK: + required: true + WIN_CSC_LINK: + required: true + CSC_KEY_PASSWORD: + required: true + WIN_CSC_KEY_PASSWORD: + required: true -permissions: - contents: read +permissions: {} jobs: build: - name: Build ${{ matrix.platform }} (electron-builder) + name: Build ${{ matrix.platform }} [electron-builder] + permissions: + contents: read strategy: matrix: include: @@ -32,6 +45,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/actions/setup-node diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86dd3fc77..c16843793 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,30 +8,45 @@ on: branches: - main -permissions: - contents: read +permissions: {} jobs: prepare: # macOS code-signing only works on `push` events and not `pull_request` events if: ${{ !startsWith(github.head_ref, 'release/v') }} name: Prepare CI runs-on: ubuntu-latest + permissions: {} steps: - - run: echo Running CI for branch ${{ github.head_ref }} + - run: echo "Running CI for branch ${GITHUB_HEAD_REF}" + env: + GITHUB_HEAD_REF: ${{ github.head_ref }} lint: name: Lint App uses: ./.github/workflows/lint.yml needs: prepare + permissions: + contents: read tests: name: Tests uses: ./.github/workflows/test.yml needs: lint - secrets: inherit + permissions: + contents: read + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} build: name: Build uses: ./.github/workflows/build.yml needs: tests - secrets: inherit + permissions: + contents: read + secrets: + OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }} + # Signing certificates + CSC_LINK: ${{ secrets.CSC_LINK }} + WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 41e9f57e5..884548430 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,20 +3,39 @@ name: Lint on: workflow_call: -permissions: - contents: read +permissions: {} jobs: - lint: - name: biomejs + lint-code: + name: Lint Code [biomejs] runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/actions/setup-node - name: Run linter run: pnpm lint:check + + lint-actions: + name: Lint GitHub Actions [actionlint] + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: .github/ + + - name: GitHub Actions linter + uses: docker://rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667 diff --git a/.github/workflows/milestone.yml b/.github/workflows/milestone.yml index 48b7e78a0..bc81fc7c3 100644 --- a/.github/workflows/milestone.yml +++ b/.github/workflows/milestone.yml @@ -7,28 +7,31 @@ on: types: - closed -permissions: - pull-requests: write +permissions: {} jobs: add-milestone: if: github.event.pull_request.merged == true runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - - name: Authenticate GitHub CLI - run: echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token - - name: Get open milestone id: milestone run: | milestone=$(gh api repos/${{ github.repository }}/milestones \ --jq '.[] | select(.state=="open") | .title' | head -n 1) echo "Found milestone: $milestone" - echo "milestone=$milestone" >> $GITHUB_OUTPUT + echo "milestone=$milestone" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Add milestone to PR if: steps.milestone.outputs.milestone != '' run: | gh pr edit ${{ github.event.pull_request.number }} \ --repo ${{ github.repository }} \ - --milestone "${{ steps.milestone.outputs.milestone }}" + --milestone "${STEPS_MILESTONE_OUTPUTS_MILESTONE}" + env: + STEPS_MILESTONE_OUTPUTS_MILESTONE: ${{ steps.milestone.outputs.milestone }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 157fafa74..6bc168e66 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,42 +2,68 @@ name: Publish on: workflow_call: + secrets: + OAUTH_CLIENT_ID: + required: true + # Signing certificates + CSC_LINK: + required: true + WIN_CSC_LINK: + required: true + CSC_KEY_PASSWORD: + required: true + WIN_CSC_KEY_PASSWORD: + required: true + # macOS specific + APPLE_ID_USERNAME: + required: true + APPLE_ID_PASSWORD: + required: true + APPLE_ID_TEAM_ID: + required: true workflow_dispatch: # For manually running release process to verify code-signing of artifacts -permissions: - contents: write +permissions: {} jobs: prepare: name: Prepare draft release runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Checkout uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 + with: + persist-credentials: false - name: Parse release branch if: startsWith(github.ref, 'refs/heads/release/') run: | # Extract the branch name (e.g. release/v1.2.3[-meta]) ref=${GITHUB_REF#refs/heads/} - echo "RELEASE_BRANCH=$ref" >> $GITHUB_ENV + echo "RELEASE_BRANCH=$ref" >> "$GITHUB_ENV" # Also export a RELEASE_TAG by removing the `release/` prefix (keeps leading 'v') tag=${ref#release/} - echo "RELEASE_TAG=$tag" >> $GITHUB_ENV + echo "RELEASE_TAG=$tag" >> "$GITHUB_ENV" shell: bash - name: Create draft release - uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 - with: - name: "${{ env.RELEASE_TAG }}" - tag_name: "${{ env.RELEASE_TAG }}" - draft: true - body: '# Gitify ${{ env.RELEASE_TAG }}' - generate_release_notes: true + run: | + gh release create "${RELEASE_TAG}" \ + --title "${RELEASE_TAG}" \ + --draft \ + --notes "# Gitify ${RELEASE_TAG}" \ + --generate-notes + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_TAG: ${{ env.RELEASE_TAG }} release: - name: Publish ${{ matrix.platform }} (electron-builder) + name: Publish ${{ matrix.platform }} [electron-builder] needs: prepare + permissions: + contents: write strategy: matrix: include: @@ -61,6 +87,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/actions/setup-node diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c56aa4d90..852bceee7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,24 +5,38 @@ on: branches: - release/v*.*.* # macOS code-signing only works on `push` events and not `pull_request` events -permissions: - contents: read +permissions: {} jobs: lint: name: Lint App uses: ./.github/workflows/lint.yml + permissions: + contents: read tests: name: Tests uses: ./.github/workflows/test.yml needs: lint - secrets: inherit + permissions: + contents: read + secrets: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} publish: name: Publish uses: ./.github/workflows/publish.yml needs: tests - secrets: inherit permissions: contents: write + secrets: + OAUTH_CLIENT_ID: ${{ secrets.OAUTH_CLIENT_ID }} + # Signing certificates + CSC_LINK: ${{ secrets.CSC_LINK }} + WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }} + # macOS specific + APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_ID_TEAM_ID: ${{ secrets.APPLE_ID_TEAM_ID }} diff --git a/.github/workflows/renovate.yml b/.github/workflows/renovate.yml index 7bcd4ea55..672e10c1b 100644 --- a/.github/workflows/renovate.yml +++ b/.github/workflows/renovate.yml @@ -10,8 +10,7 @@ on: paths: - renovate.json -permissions: - contents: read +permissions: {} jobs: renovate-config-validator: @@ -20,6 +19,9 @@ jobs: steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + sparse-checkout: renovate.json - uses: ./.github/actions/setup-node with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 21855dafb..48a0b14f2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,18 +2,24 @@ name: Test on: workflow_call: + secrets: + SONAR_TOKEN: + required: true -permissions: - contents: read +permissions: {} jobs: run-unit-tests: name: Run Tests runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Setup Node.js uses: ./.github/actions/setup-node @@ -34,6 +40,8 @@ jobs: name: SonarQube Cloud Analysis runs-on: ubuntu-latest needs: run-unit-tests + permissions: + contents: read # Only analyze PRs from the same repository. Limitation of SonarQube Cloud if: github.event.pull_request.head.repo.fork == false @@ -42,6 +50,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + persist-credentials: false - name: Setup Node.js uses: ./.github/actions/setup-node diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml index 22e9c4746..e592e4311 100644 --- a/.github/workflows/triage.yml +++ b/.github/workflows/triage.yml @@ -1,7 +1,7 @@ name: Triage PR on: - pull_request_target: + pull_request: branches: - main types: @@ -11,16 +11,14 @@ on: - synchronize - ready_for_review -permissions: - contents: read # the config file - pull-requests: write # for labeling pull requests (on: pull_request_target or on: pull_request) - statuses: write # to generate status - checks: write # to generate status +permissions: {} jobs: pr-title: name: Validate PR title runs-on: ubuntu-latest + permissions: + pull-requests: read steps: - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 env: @@ -29,5 +27,10 @@ jobs: pr-labeler: name: Auto-label PR runs-on: ubuntu-latest + permissions: + contents: read # the config file + pull-requests: write # for labeling pull requests (on: pull_request_target or on: pull_request) + statuses: write # to generate status + checks: write # to generate status steps: - uses: fuxingloh/multi-labeler@b15a54460c38f54043fa75f7b08a0e2aa5b94b5b # v4.0.0 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index ea771e251..a38166bca 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -6,12 +6,12 @@ on: types: - published # For running on release publish -permissions: - contents: read +permissions: {} jobs: redeploy-website: name: Deploy Website runs-on: ubuntu-latest + permissions: {} steps: - run: curl -X POST -d {} ${{ secrets.NETLIFY_BUILD_HOOK_URL }} diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 000000000..67110506b --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,28 @@ +name: GitHub Actions Security Analysis + +on: + push: + branches: + - main + pull_request: + branches: + - "**" + +permissions: {} + +jobs: + zizmor: + name: Run zizmor 🌈 + runs-on: ubuntu-latest + permissions: + security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. + contents: read # Only needed for private repos. Needed to clone the repo. + actions: read # Only needed for private repos. Needed for upload-sarif to read workflow run info. + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run zizmor 🌈 + uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 80f9fc744..94548f281 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ "GraphQL.vscode-graphql", "GraphQL.vscode-graphql-syntax", "SonarSource.sonarlint-vscode", - "vitest.explorer" + "vitest.explorer", + "zizmor.zizmor-vscode" ] }