diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..ed561745 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,59 @@ +name: OpenSSF Scorecard + +on: + branch_protection_rule: + schedule: + - cron: '31 5 * * 1' + push: + branches: [ main ] + workflow_dispatch: + +# Four triggers can overlap, and Scorecard reports current repository state, so a +# superseded run has nothing to contribute. Cancelling keeps the published SARIF and the +# public API entry in trigger order. +concurrency: + group: scorecard + cancel-in-progress: true + +# Least privilege by default: `analysis` names everything it needs below, and a job added +# later gets nothing until it does the same. Job-level permissions replace this block +# rather than adding to it. +permissions: {} + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + security-events: write # upload SARIF to code scanning + id-token: write # publish results to the public Scorecard API + # `contents: read` and `actions: read` are deliberately absent. Upstream ships both + # commented out, needed only for private repositories, and OSSF runs Scorecard on its + # own public repos with exactly the two permissions above. + + # Actions are pinned to full commit SHAs: a tag is mutable and can be repointed at + # other code, which is what Scorecard's own Pinned-Dependencies check looks for. + steps: + - name: Checkout + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false + + - name: Run analysis + uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: Upload artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: Upload to code scanning + uses: github/codeql-action/upload-sarif@42947a340483f03ba47bb1a039b2c519aab3df85 # v3.37.8 + with: + sarif_file: results.sarif diff --git a/CHANGELOG.md b/CHANGELOG.md index 736421bc..50575764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Types of changes: ### Dependencies ### Other +- Added an OpenSSF Scorecard workflow. It grades the repository's supply-chain practices and publishes the score to the public Scorecard API, so a third party computes the number rather than us. ([#412](https://github.com/qBraid/pyqasm/pull/412)) - Switched PyPI publishing from a long-lived `PYPI_API_TOKEN` repository secret to trusted publishing. The publish job now mints a short-lived OIDC credential scoped to that one workflow, and the action attaches PEP 740 attestations recording the repository, workflow and commit SHA behind each uploaded file. Attestations apply to releases published after this merges, not retroactively. ([#411](https://github.com/qBraid/pyqasm/pull/411)) - Fixed the pre-release build stamping a version that `pyqasm.__version__` and the package metadata spelled differently. `pre_build.sh` wrote `1.1.0-a.0` into `pyproject.toml`, setuptools normalized that to `1.1.0a0` for the metadata, and `_version.py` kept the raw string, so `pip show pyqasm` and `pyqasm.__version__` disagreed and `test_sdist.sh` failed its version check. The stamped version is now normalized to PEP 440 before it is written. ([#414](https://github.com/qBraid/pyqasm/pull/414)) - Fixed the pre-release workflow publishing its source distribution under the released version instead of the pre-release one. `build_sdist.sh` ran `git reset --hard` and `git clean -xdf`, which discarded the `pyproject.toml` version that the preceding step had just stamped, so a run that built `1.1.0a0` wheels built a `1.1.0` sdist and PyPI rejected it as a duplicate. `pre_build.sh` already resets the tree, so the second reset is gone. It also no longer destroys uncommitted work when the script is run locally. ([#413](https://github.com/qBraid/pyqasm/pull/413))