From 89b7e7d792717bcdf9dca23454ea5c508bb89a0e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Fri, 3 Nov 2023 15:51:07 +0000 Subject: [PATCH 01/26] Cypress workflow: remove redundant `rust-crypto` param https://github.com/matrix-org/matrix-react-sdk/pull/11828 removes the `rust-crypto` input param from the reusable cypress workflow. This gets rid of it on the calling side. --- .github/workflows/cypress.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index a40711a9c..0bcc98845 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -33,7 +33,6 @@ jobs: TCMS_PASSWORD: ${{ secrets.TCMS_PASSWORD }} with: react-sdk-repository: matrix-org/matrix-react-sdk - rust-crypto: true # We want to make the cypress tests a required check for the merge queue. # From ffb4cae792ba29b13a9bf90f61068b1be5df6acf Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Thu, 9 Nov 2023 20:00:45 +0530 Subject: [PATCH 02/26] Update workfile --- .github/workflows/cypress.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index a40711a9c..63c54dab6 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -20,7 +20,7 @@ jobs: # from creeping in. They take a long time to run and consume 4 concurrent runners. if: github.event.workflow_run.event == 'merge_group' - uses: matrix-org/matrix-react-sdk/.github/workflows/cypress.yaml@v3.83.0-rc.1 + uses: matrix-org/matrix-react-sdk/.github/workflows/cypress.yaml@03b01b4a50d0f3fbbfa6c1a9314ef2d346d089d4 permissions: actions: read issues: read From 5c160d0f45b15d7cb8f3aca6b7e8cd3c301ee829 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Thu, 9 Nov 2023 16:41:15 +0000 Subject: [PATCH 03/26] Shorten TimelineWindow when an event is removed (#3862) * Shorten TimelineWindow when an event is removed Needed for the fix for https://github.com/vector-im/element-web/issues/26498 * Declare onTimelineEvent as a standard method to match surrounding code --- spec/test-utils/test-utils.ts | 1 + spec/unit/timeline-window.spec.ts | 62 +++++++++++++++++++++++++++++++ src/timeline-window.ts | 23 ++++++++++++ 3 files changed, 86 insertions(+) diff --git a/spec/test-utils/test-utils.ts b/spec/test-utils/test-utils.ts index d75928030..1e4f8d38e 100644 --- a/spec/test-utils/test-utils.ts +++ b/spec/test-utils/test-utils.ts @@ -315,6 +315,7 @@ export interface IMessageOpts { event?: boolean; relatesTo?: IEventRelation; ts?: number; + unsigned?: IUnsigned; } /** diff --git a/spec/unit/timeline-window.spec.ts b/spec/unit/timeline-window.spec.ts index f786a513d..ddb2a48d3 100644 --- a/spec/unit/timeline-window.spec.ts +++ b/spec/unit/timeline-window.spec.ts @@ -22,12 +22,15 @@ import { Room } from "../../src/models/room"; import { EventTimeline } from "../../src/models/event-timeline"; import { TimelineIndex, TimelineWindow } from "../../src/timeline-window"; import { mkMessage } from "../test-utils/test-utils"; +import { MatrixEvent } from "../../src/models/event"; const ROOM_ID = "roomId"; const USER_ID = "userId"; const mockClient = { getEventTimeline: jest.fn(), paginateEventTimeline: jest.fn(), + supportsThreads: jest.fn(), + getUserId: jest.fn().mockReturnValue(USER_ID), } as unknown as MockedObject; /* @@ -64,6 +67,23 @@ function addEventsToTimeline(timeline: EventTimeline, numEvents: number, toStart } } +function createEvents(numEvents: number): Array { + const ret = []; + + for (let i = 0; i < numEvents; i++) { + ret.push( + mkMessage({ + room: ROOM_ID, + user: USER_ID, + event: true, + unsigned: { age: 1 }, + }), + ); + } + + return ret; +} + /* * create a pair of linked timelines */ @@ -412,4 +432,46 @@ describe("TimelineWindow", function () { expect(timelineWindow.canPaginate(EventTimeline.FORWARDS)).toBe(true); }); }); + + function idsOf(events: Array): Array { + return events.map((e) => (e ? e.getId() ?? "MISSING_ID" : "MISSING_EVENT")); + } + + describe("removing events", () => { + it("should shorten if removing an event within the window makes it overflow", function () { + // Given a room with events in two timelines + const room = new Room(ROOM_ID, mockClient, USER_ID, { timelineSupport: true }); + const timelineSet = room.getUnfilteredTimelineSet(); + const liveTimeline = room.getLiveTimeline(); + const oldTimeline = room.addTimeline(); + liveTimeline.setNeighbouringTimeline(oldTimeline, EventTimeline.BACKWARDS); + oldTimeline.setNeighbouringTimeline(liveTimeline, EventTimeline.FORWARDS); + + const oldEvents = createEvents(5); + const liveEvents = createEvents(5); + const [, , e3, e4, e5] = oldEvents; + const [, e7, e8, e9, e10] = liveEvents; + room.addLiveEvents(liveEvents); + room.addEventsToTimeline(oldEvents, true, oldTimeline); + + // And 2 windows over the timelines in this room + const oldWindow = new TimelineWindow(mockClient, timelineSet); + oldWindow.load(e5.getId(), 6); + expect(idsOf(oldWindow.getEvents())).toEqual(idsOf([e5, e4, e3])); + + const newWindow = new TimelineWindow(mockClient, timelineSet); + newWindow.load(e9.getId(), 4); + expect(idsOf(newWindow.getEvents())).toEqual(idsOf([e7, e8, e9, e10])); + + // When I remove an event + room.removeEvent(e8.getId()!); + + // Then the affected timeline is shortened (because it would have + // been too long with the removed event gone) + expect(idsOf(newWindow.getEvents())).toEqual(idsOf([e7, e9, e10])); + + // And the unaffected one is not + expect(idsOf(oldWindow.getEvents())).toEqual(idsOf([e5, e4, e3])); + }); + }); }); diff --git a/src/timeline-window.ts b/src/timeline-window.ts index 5f0d88569..0022ae871 100644 --- a/src/timeline-window.ts +++ b/src/timeline-window.ts @@ -21,6 +21,7 @@ import { logger } from "./logger"; import { MatrixClient } from "./client"; import { EventTimelineSet } from "./models/event-timeline-set"; import { MatrixEvent } from "./models/event"; +import { Room, RoomEvent } from "./models/room"; /** * @internal @@ -74,6 +75,10 @@ export class TimelineWindow { * are received from /sync; you should arrange to call {@link TimelineWindow#paginate} * on {@link RoomEvent.Timeline} events. * + *

Note that constructing an instance of this class for a room adds a + * listener for RoomEvent.Timeline events which is never removed. In theory + * this should not cause a leak since the EventEmitter uses weak mappings. + * * @param client - MatrixClient to be used for context/pagination * requests. * @@ -87,6 +92,7 @@ export class TimelineWindow { opts: IOpts = {}, ) { this.windowLimit = opts.windowLimit || 1000; + timelineSet.room?.on(RoomEvent.Timeline, this.onTimelineEvent.bind(this)); } /** @@ -193,6 +199,23 @@ export class TimelineWindow { return false; } + private onTimelineEvent(_event?: MatrixEvent, _room?: Room, _atStart?: boolean, removed?: boolean): void { + if (removed) { + this.onEventRemoved(); + } + } + + /** + * If an event was removed, meaning this window is longer than the timeline, + * shorten the window. + */ + private onEventRemoved(): void { + const events = this.getEvents(); + if (events.length > 0 && events[events.length - 1] === undefined && this.end) { + this.end.index--; + } + } + /** * Check if this window can be extended * From 24ed0302946afff32084b29d7ed75e6dff5f82cc Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Nov 2023 20:54:29 +0000 Subject: [PATCH 04/26] Extend release automation with GPG signing, assets & changelog merging (#3852) * Tidy reusable release workflow Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add ability to include upstream changes Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add ability to upload assets and gpg sign them Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update relative composite actions Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Wire up validating release tarball signature Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Validate release has expected assets Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Paths Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Use gpg outputs for email instead of scraping it ourselves Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * v6 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Extract pre-release and post-merge-master scripts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reuse pre-release and post-merge-master scripts in gha Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Cull unused vars Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove unused variables Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify and fix merge-release-notes script Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Tidy release automation Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update release.sh * Move environment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * s/includes/contains/ Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate uses syntax Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix action-repo calls Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix RELEASE_NOTES env Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix if check Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix gpg tag signing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Cull stale params Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix sign-release-tarball paths being outside the workspace Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix gpg validation (of course wget uses `-O` and not `-o`) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix expected asset assertion Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix release publish mode Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../actions/sign-release-tarball/action.yml | 28 ++++ .../actions/upload-release-assets/action.yml | 41 +++++ .github/workflows/release-action.yml | 153 ++++++++++++++++-- scripts/release/merge-release-notes.js | 79 +++++++++ 4 files changed, 290 insertions(+), 11 deletions(-) create mode 100644 .github/actions/sign-release-tarball/action.yml create mode 100644 .github/actions/upload-release-assets/action.yml create mode 100755 scripts/release/merge-release-notes.js diff --git a/.github/actions/sign-release-tarball/action.yml b/.github/actions/sign-release-tarball/action.yml new file mode 100644 index 000000000..cd663cd87 --- /dev/null +++ b/.github/actions/sign-release-tarball/action.yml @@ -0,0 +1,28 @@ +name: Sign Release Tarball +description: Generates signature for release tarball and uploads it as a release asset +inputs: + gpg-fingerprint: + description: Fingerprint of the GPG key to use for signing the tarball. + required: true + upload-url: + description: GitHub release upload URL to upload the signature file to. + required: true +runs: + using: composite + steps: + - name: Generate tarball signature + shell: bash + run: | + git -c tar.tar.gz.command='gzip -cn' archive --format=tar.gz --prefix="${REPO#*/}-${VERSION#v}/" -o "/tmp/${VERSION}.tar.gz" "${VERSION}" + gpg -u "$GPG_FINGERPRINT" --armor --output "${VERSION}.tar.gz.asc" --detach-sig "/tmp/${VERSION}.tar.gz" + rm "/tmp/${VERSION}.tar.gz" + env: + GPG_FINGERPRINT: ${{ inputs.gpg-fingerprint }} + REPO: ${{ github.repository }} + + - name: Upload tarball signature + if: ${{ inputs.upload-url }} + uses: shogo82148/actions-upload-release-asset@dccd6d23e64fd6a746dce6814c0bde0a04886085 # v1 + with: + upload_url: ${{ inputs.upload-url }} + asset_path: ${{ env.VERSION }}.tar.gz.asc diff --git a/.github/actions/upload-release-assets/action.yml b/.github/actions/upload-release-assets/action.yml new file mode 100644 index 000000000..25eb7f039 --- /dev/null +++ b/.github/actions/upload-release-assets/action.yml @@ -0,0 +1,41 @@ +name: Upload release assets +description: Uploads assets to an existing release and optionally signs them +inputs: + gpg-fingerprint: + description: Fingerprint of the GPG key to use for signing the assets, if any. + required: false + upload-url: + description: GitHub release upload URL to upload the assets to. + required: true + asset-path: + description: | + The path to the asset you want to upload, if any. You can use glob patterns here. + Will be GPG signed and an `.asc` file included in the release artifacts if `gpg-fingerprint` is set. + required: true +runs: + using: composite + steps: + - name: Sign assets + if: inputs.gpg-fingerprint + shell: bash + run: | + for FILE in $ASSET_PATH + do + gpg -u "$GPG_FINGERPRINT" --armor --output "$FILE".asc --detach-sig "$FILE" + done + env: + GPG_FINGERPRINT: ${{ inputs.gpg-fingerprint }} + ASSET_PATH: ${{ inputs.asset-path }} + + - name: Upload asset signatures + if: inputs.gpg-fingerprint + uses: shogo82148/actions-upload-release-asset@dccd6d23e64fd6a746dce6814c0bde0a04886085 # v1 + with: + upload_url: ${{ inputs.upload-url }} + asset_path: ${{ inputs.asset-path }}.asc + + - name: Upload assets + uses: shogo82148/actions-upload-release-asset@dccd6d23e64fd6a746dce6814c0bde0a04886085 # v1 + with: + upload_url: ${{ inputs.upload-url }} + asset_path: ${{ inputs.asset-path }} diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index 715478e71..aba9ae28d 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -6,6 +6,10 @@ on: required: true NPM_TOKEN: required: false + GPG_PASSPHRASE: + required: false + GPG_PRIVATE_KEY: + required: false inputs: final: description: Make final release @@ -22,11 +26,39 @@ on: `version` can be `"current"` to leave it at the current version. type: string required: false + include-changes: + description: Project to include changelog entries from in this release. + type: string + required: false + gpg-fingerprint: + description: Fingerprint of the GPG key to use for signing the git tag and assets, if any. + type: string + required: false + asset-path: + description: | + The path to the asset you want to upload, if any. You can use glob patterns here. + Will be GPG signed and an `.asc` file included in the release artifacts if `gpg-fingerprint` is set. + type: string + required: false + expected-asset-count: + description: The number of expected assets, including signatures, excluding generated zip & tarball. + type: number + required: false jobs: release: name: Release runs-on: ubuntu-latest + environment: Release steps: + - name: Load GPG key + id: gpg + if: inputs.gpg-fingerprint + uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + fingerprint: ${{ inputs.gpg-fingerprint }} + - name: Get draft release id: release uses: cardinalby/git-get-release-action@cedef2faf69cb7c55b285bad07688d04430b7ada # v1 @@ -49,11 +81,24 @@ jobs: persist-credentials: false path: .action-repo sparse-checkout: | + .github/actions scripts/release - - name: Load version - run: echo "VERSION=$VERSION" >> $GITHUB_ENV + - name: Prepare variables + id: prepare + run: | + echo "VERSION=$VERSION" >> $GITHUB_ENV + { + echo "RELEASE_NOTES<> $GITHUB_ENV + + HAS_DIST=0 + jq -e .scripts.dist package.json >/dev/null 2>&1 && HAS_DIST=1 + echo "has-dist-script=$HAS_DIST" >> $GITHUB_OUTPUT env: + BODY: ${{ steps.release.outputs.body }} VERSION: ${{ steps.release.outputs.tag_name }} - name: Finalise version @@ -73,8 +118,10 @@ jobs: run: "yarn install --frozen-lockfile" - name: Update dependencies + id: update-dependencies if: inputs.dependencies run: | + UPDATED=() while IFS= read -r DEPENDENCY; do [ -z "$DEPENDENCY" ] && continue IFS="=" read -r PACKAGE UPDATE_VERSION <<< "$DEPENDENCY" @@ -98,7 +145,11 @@ jobs: yarn upgrade "$PACKAGE@$UPDATE_VERSION" --exact git add -u git commit -m "Upgrade $PACKAGE to $UPDATE_VERSION" + UPDATED+=("$PACKAGE") done <<< "$DEPENDENCIES" + + JSON=$(jq --compact-output --null-input '$ARGS.positional' --args -- "${UPDATED[@]}") + echo "updated=$JSON" >> $GITHUB_OUTPUT env: DEPENDENCIES: ${{ inputs.dependencies }} @@ -115,6 +166,28 @@ jobs: - name: Bump package.json version run: yarn version --no-git-tag-version --new-version "$VERSION" + - name: Ingest upstream changes + if: | + inputs.dependencies && + inputs.include-changes && + contains(fromJSON(steps.update-dependencies.outputs.updated), inputs.include-changes) + uses: actions/github-script@v6 + env: + RELEASE_ID: ${{ steps.upstream-release.outputs.body }} + DEPENDENCY: ${{ inputs.include-changes }} + with: + retries: 3 + script: | + const { RELEASE_ID: releaseId, DEPENDENCY } = process.env; + const { owner, repo } = context.repo; + const script = require("./.action-repo/scripts/release/merge-release-notes.js"); + const notes = await script({ + github, + releaseId, + dependencies: [DEPENDENCY], + }); + core.exportVariable("RELEASE_NOTES", notes); + - name: Add to CHANGELOG.md if: inputs.mode == 'final' run: | @@ -125,25 +198,84 @@ jobs: echo "$HEADER" printf '=%.0s' $(seq ${#HEADER}) echo "" - echo "$BODY" + echo "$RELEASE_NOTES" echo "" } > CHANGELOG.md cat CHANGELOG.md.old >> CHANGELOG.md rm CHANGELOG.md.old git add CHANGELOG.md - env: - BODY: ${{ steps.release.outputs.body }} - name: Run pre-release script to update package.json fields run: | ./.action-repo/scripts/release/pre-release.sh git add package.json - - name: Commit and push changes + - name: Commit changes + run: git commit -m "$VERSION" + + - name: Build assets + if: steps.prepare.outputs.has-dist-script + run: DIST_VERSION="$VERSION" yarn dist + + - name: Upload release assets & signatures + if: inputs.asset-path + uses: ./.action-repo/.github/actions/upload-release-assets + with: + gpg-fingerprint: ${{ inputs.gpg-fingerprint }} + upload-url: ${{ steps.release.outputs.upload_url }} + asset-path: ${{ inputs.asset-path }} + + - name: Create signed tag + if: inputs.gpg-fingerprint run: | - git commit -m "$VERSION" - git push origin staging + GIT_COMMITTER_EMAIL="$SIGNING_ID" GPG_TTY=$(tty) git tag -u "$SIGNING_ID" -m "Release $VERSION" "$VERSION" + env: + SIGNING_ID: ${{ steps.gpg.outputs.email }} + + - name: Generate & upload tarball signature + if: inputs.gpg-fingerprint + uses: ./.action-repo/.github/actions/sign-release-tarball + with: + gpg-fingerprint: ${{ inputs.gpg-fingerprint }} + upload-url: ${{ steps.release.outputs.upload_url }} + + # We defer pushing changes until after the release assets are built, + # signed & uploaded to improve the atomicity of this action. + - name: Push changes to staging + run: | + git push origin staging $TAG + git reset --hard + env: + TAG: ${{ inputs.gpg-fingerprint && env.VERSION || '' }} + + - name: Validate tarball signature + if: inputs.gpg-fingerprint + run: | + wget https://github.com/$GITHUB_REPOSITORY/archive/refs/tags/$VERSION.tar.gz + gpg --verify "$VERSION.tar.gz.asc" "$VERSION.tar.gz" + + - name: Validate release has expected assets + if: inputs.expected-asset-count + uses: actions/github-script@v6 + env: + RELEASE_ID: ${{ steps.release.outputs.id }} + EXPECTED_ASSET_COUNT: ${{ inputs.expected-asset-count }} + with: + retries: 3 + script: | + const { RELEASE_ID: release_id, EXPECTED_ASSET_COUNT } = process.env; + const { owner, repo } = context.repo; + + const { data: release } = await github.rest.repos.getRelease({ + owner, + repo, + release_id, + }); + + if (release.assets.length !== parseInt(EXPECTED_ASSET_COUNT, 10)) { + core.setFailed(`Found ${release.assets.length} assets but expected ${EXPECTED_ASSET_COUNT}`); + } - name: Merge to master if: inputs.final @@ -154,15 +286,13 @@ jobs: - name: Publish release uses: actions/github-script@v6 - id: my-script env: RELEASE_ID: ${{ steps.release.outputs.id }} FINAL: ${{ inputs.final }} with: - result-encoding: string retries: 3 script: | - let { RELEASE_ID: release_id, VERSION, FINAL } = process.env; + const { RELEASE_ID: release_id, RELEASE_NOTES, VERSION, FINAL } = process.env; const { owner, repo } = context.repo; const opts = { @@ -172,6 +302,7 @@ jobs: tag_name: VERSION, name: VERSION, draft: false, + body: RELEASE_NOTES, }; if (FINAL == "true") { diff --git a/scripts/release/merge-release-notes.js b/scripts/release/merge-release-notes.js new file mode 100755 index 000000000..f98aa46e9 --- /dev/null +++ b/scripts/release/merge-release-notes.js @@ -0,0 +1,79 @@ +#!/usr/bin/env node + +const fs = require("fs"); + +async function getRelease(github, dependency) { + const upstreamPackageJson = JSON.parse(fs.readFileSync(`./node_modules/${dependency}/package.json`, "utf8")); + const [owner, repo] = upstreamPackageJson.repository.url.split("/").slice(-2); + const tag = `v${upstreamPackageJson.version}`; + + const response = await github.rest.repos.getReleaseByTag({ + owner, + repo, + tag, + }); + return response.data; +} + +const main = async ({ github, releaseId, dependencies }) => { + const { GITHUB_REPOSITORY } = process.env; + const [owner, repo] = GITHUB_REPOSITORY.split("/"); + + const sections = new Map(); + let heading = null; + for (const dependency of dependencies) { + const release = await getRelease(github, dependency); + for (const line of release.body.split("\n")) { + if (line.startsWith("#")) { + heading = line; + sections.set(heading, []); + continue; + } + if (heading && line) { + sections.get(heading).push(line); + } + } + } + + const { data: release } = await github.rest.repos.getRelease({ + owner, + repo, + release_id: releaseId, + }); + + heading = null; + const output = []; + for (const line of [...release.body.split("\n"), null]) { + if (line === null || line.startsWith("#")) { + if (heading && sections.has(heading)) { + const lastIsBlank = !output.at(-1)?.trim(); + if (lastIsBlank) output.pop(); + output.push(...sections.get(heading)); + if (lastIsBlank) output.push(""); + } + heading = line; + } + output.push(line); + } + + return output.join("\n"); +}; + +// This is just for testing locally +// Needs environment variables GITHUB_TOKEN & GITHUB_REPOSITORY +if (require.main === module) { + const { Octokit } = require("@octokit/rest"); + const github = new Octokit({ auth: process.env.GITHUB_TOKEN }); + if (process.argv.length < 4) { + // eslint-disable-next-line no-console + console.error("Usage: node merge-release-notes.js owner/repo:release_id npm-package-name ..."); + process.exit(1); + } + const [releaseId, ...dependencies] = process.argv.slice(2); + main({ github, releaseId, dependencies }).then((output) => { + // eslint-disable-next-line no-console + console.log(output); + }); +} + +module.exports = main; From 437b7ff780126c2d4d5a2da7e0d443512cf8de22 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Fri, 10 Nov 2023 00:06:48 +0000 Subject: [PATCH 05/26] Revert "Better fallback for unavailable event age (#3854)" (#3870) This reverts commit 84bd8ab81faf90983690801a54020eb31be24844. --- spec/unit/matrixrtc/CallMembership.spec.ts | 4 +--- spec/unit/matrixrtc/mocks.ts | 2 +- src/matrixrtc/CallMembership.ts | 2 +- src/models/event.ts | 19 ++----------------- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/spec/unit/matrixrtc/CallMembership.spec.ts b/spec/unit/matrixrtc/CallMembership.spec.ts index eb4b1232a..4bc5492e0 100644 --- a/spec/unit/matrixrtc/CallMembership.spec.ts +++ b/spec/unit/matrixrtc/CallMembership.spec.ts @@ -85,9 +85,7 @@ describe("CallMembership", () => { it("considers memberships expired when local age large", () => { const fakeEvent = makeMockEvent(1000); - const evAge = 6000; - fakeEvent.getLocalAge = jest.fn().mockReturnValue(evAge); - fakeEvent.localTimestamp = Date.now() - evAge; + fakeEvent.getLocalAge = jest.fn().mockReturnValue(6000); const membership = new CallMembership(fakeEvent, membershipTemplate); expect(membership.isExpired()).toEqual(true); }); diff --git a/spec/unit/matrixrtc/mocks.ts b/spec/unit/matrixrtc/mocks.ts index c373cdf9d..f710c49ab 100644 --- a/spec/unit/matrixrtc/mocks.ts +++ b/spec/unit/matrixrtc/mocks.ts @@ -61,7 +61,7 @@ export function mockRTCEvent( getSender: jest.fn().mockReturnValue("@mock:user.example"), getTs: jest.fn().mockReturnValue(1000), getLocalAge: getLocalAgeFn, - localTimestamp: Date.now() - getLocalAgeFn(), + localTimestamp: Date.now(), getRoomId: jest.fn().mockReturnValue(roomId), sender: { userId: "@mock:user.example", diff --git a/src/matrixrtc/CallMembership.ts b/src/matrixrtc/CallMembership.ts index d24b32add..d304c9df4 100644 --- a/src/matrixrtc/CallMembership.ts +++ b/src/matrixrtc/CallMembership.ts @@ -91,7 +91,7 @@ export class CallMembership { } public isExpired(): boolean { - return this.getMsUntilExpiry() <= 0; + return this.getAbsoluteExpiry() < this.parentEvent.getTs() + this.parentEvent.getLocalAge(); } public getActiveFoci(): Focus[] { diff --git a/src/models/event.ts b/src/models/event.ts index 66c410ba2..a3a6e46d1 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -390,7 +390,7 @@ export class MatrixEvent extends TypedEventEmitter Date: Fri, 10 Nov 2023 16:57:50 +0000 Subject: [PATCH 06/26] Bump matrix-sdk-crypto-wasm to 3.0.1 (#3849) * Bump matrix-sdk-crypto-wasm to 3.0.0 ... which changes the API of `bootstrapCrossSigning` a bit. * Fix class names in test * fix brokenness in bootstrapCrossSigning * Bump to `matrix-sdk-crypto-wasm` 3.0.1 --- package.json | 2 +- .../rust-crypto/OutgoingRequestProcessor.spec.ts | 10 +++++----- src/rust-crypto/CrossSigningIdentity.ts | 16 +++++++++++----- src/rust-crypto/OutgoingRequestProcessor.ts | 6 +++--- yarn.lock | 8 ++++---- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index a26a0c0eb..3b5f4f741 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ ], "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/matrix-sdk-crypto-wasm": "^2.2.0", + "@matrix-org/matrix-sdk-crypto-wasm": "^3.0.1", "another-json": "^0.2.0", "bs58": "^5.0.0", "content-type": "^1.0.4", diff --git a/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts b/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts index da8dc37a6..3501ec8fa 100644 --- a/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts +++ b/spec/unit/rust-crypto/OutgoingRequestProcessor.spec.ts @@ -24,7 +24,7 @@ import { KeysUploadRequest, RoomMessageRequest, SignatureUploadRequest, - SigningKeysUploadRequest, + UploadSigningKeysRequest, ToDeviceRequest, } from "@matrix-org/matrix-sdk-crypto-wasm"; @@ -173,10 +173,10 @@ describe("OutgoingRequestProcessor", () => { httpBackend.verifyNoOutstandingRequests(); }); - it("should handle SigningKeysUploadRequests without UIA", async () => { + it("should handle UploadSigningKeysRequest without UIA", async () => { // first, mock up a request as we might expect to receive it from the Rust layer ... const testReq = { foo: "bar" }; - const outgoingRequest = new SigningKeysUploadRequest(JSON.stringify(testReq)); + const outgoingRequest = new UploadSigningKeysRequest(JSON.stringify(testReq)); // ... then poke the request into the OutgoingRequestProcessor under test const reqProm = processor.makeOutgoingRequest(outgoingRequest); @@ -200,10 +200,10 @@ describe("OutgoingRequestProcessor", () => { httpBackend.verifyNoOutstandingRequests(); }); - it("should handle SigningKeysUploadRequests with UIA", async () => { + it("should handle UploadSigningKeysRequest with UIA", async () => { // first, mock up a request as we might expect to receive it from the Rust layer ... const testReq = { foo: "bar" }; - const outgoingRequest = new SigningKeysUploadRequest(JSON.stringify(testReq)); + const outgoingRequest = new UploadSigningKeysRequest(JSON.stringify(testReq)); // also create a UIA callback const authCallback: UIAuthCallback = async (makeRequest) => { diff --git a/src/rust-crypto/CrossSigningIdentity.ts b/src/rust-crypto/CrossSigningIdentity.ts index 981fe8ec6..8598dab61 100644 --- a/src/rust-crypto/CrossSigningIdentity.ts +++ b/src/rust-crypto/CrossSigningIdentity.ts @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { OlmMachine, CrossSigningStatus } from "@matrix-org/matrix-sdk-crypto-wasm"; +import { OlmMachine, CrossSigningStatus, CrossSigningBootstrapRequests } from "@matrix-org/matrix-sdk-crypto-wasm"; import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm"; import { BootstrapCrossSigningOpts } from "../crypto-api"; import { logger } from "../logger"; -import { OutgoingRequest, OutgoingRequestProcessor } from "./OutgoingRequestProcessor"; +import { OutgoingRequestProcessor } from "./OutgoingRequestProcessor"; import { UIAuthCallback } from "../interactive-auth"; import { ServerSideSecretStorage } from "../secret-storage"; @@ -118,7 +118,7 @@ export class CrossSigningIdentity { private async resetCrossSigning(authUploadDeviceSigningKeys?: UIAuthCallback): Promise { // XXX: We must find a way to make this atomic, currently if the user does not remember his account password // or 4S passphrase/key the process will fail in a bad state, with keys rotated but not uploaded or saved in 4S. - const outgoingRequests: Array = await this.olmMachine.bootstrapCrossSigning(true); + const outgoingRequests: CrossSigningBootstrapRequests = await this.olmMachine.bootstrapCrossSigning(true); // If 4S is configured we need to udpate it. if (await this.secretStorage.hasKey()) { @@ -128,8 +128,14 @@ export class CrossSigningIdentity { await this.exportCrossSigningKeysToStorage(); } logger.log("bootStrapCrossSigning: publishing keys to server"); - for (const req of outgoingRequests) { - await this.outgoingRequestProcessor.makeOutgoingRequest(req, authUploadDeviceSigningKeys); + for (const req of [ + outgoingRequests.uploadKeysRequest, + outgoingRequests.uploadSigningKeysRequest, + outgoingRequests.uploadSignaturesRequest, + ]) { + if (req) { + await this.outgoingRequestProcessor.makeOutgoingRequest(req, authUploadDeviceSigningKeys); + } } } diff --git a/src/rust-crypto/OutgoingRequestProcessor.ts b/src/rust-crypto/OutgoingRequestProcessor.ts index 335e11a26..1fbd2d643 100644 --- a/src/rust-crypto/OutgoingRequestProcessor.ts +++ b/src/rust-crypto/OutgoingRequestProcessor.ts @@ -23,7 +23,7 @@ import { RoomMessageRequest, SignatureUploadRequest, ToDeviceRequest, - SigningKeysUploadRequest, + UploadSigningKeysRequest, } from "@matrix-org/matrix-sdk-crypto-wasm"; import { logger } from "../logger"; @@ -62,7 +62,7 @@ export class OutgoingRequestProcessor { ) {} public async makeOutgoingRequest( - msg: OutgoingRequest | SigningKeysUploadRequest, + msg: OutgoingRequest | UploadSigningKeysRequest, uiaCallback?: UIAuthCallback, ): Promise { let resp: string; @@ -92,7 +92,7 @@ export class OutgoingRequestProcessor { `/_matrix/client/v3/rooms/${encodeURIComponent(msg.room_id)}/send/` + `${encodeURIComponent(msg.event_type)}/${encodeURIComponent(msg.txn_id)}`; resp = await this.rawJsonRequest(Method.Put, path, {}, msg.body); - } else if (msg instanceof SigningKeysUploadRequest) { + } else if (msg instanceof UploadSigningKeysRequest) { await this.makeRequestWithUIA( Method.Post, "/_matrix/client/v3/keys/device_signing/upload", diff --git a/yarn.lock b/yarn.lock index afef16401..6e6ea3a0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1590,10 +1590,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@matrix-org/matrix-sdk-crypto-wasm@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-2.2.0.tgz#7c60afe01915281a6b71502821bc8e01afbfa70d" - integrity sha512-txmvaTiZpVV0/kWCRcE7tZvRESCEc1ynLJDVh9OUsFlaXfl13c7qdD3E6IJEJ8YiPMIn+PHogdfBZsO84reaMg== +"@matrix-org/matrix-sdk-crypto-wasm@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-3.0.1.tgz#56a0376f8a389264bcf4d5325b378a71f18b7664" + integrity sha512-r0PBfUKlLHm67+fpIV21netX5+DujbY2XjJy7JUGJ55oW4XWBNbSf9vElfaQkrdt/iDscL/8I5PoD5lCuVW6zA== "@matrix-org/olm@3.2.15": version "3.2.15" From 625753c388b8a2fdfd87de35bb24a9fefc2ba2b6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 10 Nov 2023 20:30:33 +0000 Subject: [PATCH 07/26] Update tests.yml (#3847) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5e77bb798..69a570e27 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: specs: [integ, unit] - node: [18, "*"] + node: [18, "lts/*", 21] steps: - name: Checkout code uses: actions/checkout@v4 From 9efc0acb9d277108ca3c1e485211f1d5e8876b8d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Sat, 11 Nov 2023 06:53:14 +0000 Subject: [PATCH 08/26] Automate checking there is no published release using the version already (#3865) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index aba9ae28d..a954a425c 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -105,6 +105,21 @@ jobs: if: inputs.mode == 'final' run: echo "VERSION=$(echo $VERSION | cut -d- -f1)" >> $GITHUB_ENV + - name: Check version number not in use + uses: actions/github-script@v6 + with: + script: | + const { VERSION } = process.env; + github.rest.repos.getReleaseByTag({ + owner: context.repo.owner, + repo: context.repo.repo, + tag: VERSION, + }).then(() => { + core.setFailed(`Version ${VERSION} already exists`); + }).catch(() => { + // This is fine, we expect there to not be any release with this version yet + }); + - name: Set up git run: | git config --global user.email "releases@riot.im" From 882dc920c3dba7da2c301d13fc6a99aea6137a5c Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Sat, 11 Nov 2023 12:50:36 +0530 Subject: [PATCH 09/26] Ensure `setUserCreator` is called when a store is assigned (#3867) * Add method to set store * Use not null assertion * Use getter/setter * No need for check if we use setter --- src/client.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 7a1d997cc..542f18515 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1217,7 +1217,7 @@ export class MatrixClient extends TypedEventEmitter(this); public olmVersion: [number, number, number] | null = null; // populated after initCrypto public usingExternalCrypto = false; - public store: Store; + private _store!: Store; public deviceId: string | null; public credentials: { userId: string | null }; @@ -1332,7 +1332,6 @@ export class MatrixClient extends TypedEventEmitter User.createUser(userId, this)); this.deviceId = opts.deviceId || null; this.sessionId = randomString(10); @@ -1497,6 +1496,15 @@ export class MatrixClient extends TypedEventEmitter User.createUser(userId, this)); + } + + public get store(): Store { + return this._store; + } + /** * High level helper method to begin syncing and poll for new events. To listen for these * events, add a listener for {@link ClientEvent.Event} From d2e951738ac58baf136921f50ff5adfe6458c610 Mon Sep 17 00:00:00 2001 From: Johannes Marbach Date: Sat, 11 Nov 2023 08:21:31 +0100 Subject: [PATCH 10/26] Automatically add tech-debt issues to the right project (#3872) --- .github/workflows/triage-labelled.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/triage-labelled.yml diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml new file mode 100644 index 000000000..6d83a8a47 --- /dev/null +++ b/.github/workflows/triage-labelled.yml @@ -0,0 +1,10 @@ +name: Move labelled issues to correct projects + +on: + issues: + types: [labeled] + +jobs: + call-triage-labelled: + uses: vector-im/element-web/.github/workflows/triage-labelled.yml@develop + secrets: inherit From 46a6a76a41c7845c93c9a7de0332367ca7cdb473 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 13 Nov 2023 10:11:27 +0100 Subject: [PATCH 11/26] [Backport staging] Ensure `setUserCreator` is called when a store is assigned (#3876) Co-authored-by: R Midhun Suresh --- src/client.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/client.ts b/src/client.ts index 0baa52f21..b496c6133 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1227,7 +1227,7 @@ export class MatrixClient extends TypedEventEmitter(this); public olmVersion: [number, number, number] | null = null; // populated after initCrypto public usingExternalCrypto = false; - public store: Store; + private _store!: Store; public deviceId: string | null; public credentials: { userId: string | null }; @@ -1342,7 +1342,6 @@ export class MatrixClient extends TypedEventEmitter User.createUser(userId, this)); this.deviceId = opts.deviceId || null; this.sessionId = randomString(10); @@ -1507,6 +1506,15 @@ export class MatrixClient extends TypedEventEmitter User.createUser(userId, this)); + } + + public get store(): Store { + return this._store; + } + /** * High level helper method to begin syncing and poll for new events. To listen for these * events, add a listener for {@link ClientEvent.Event} From e01a1d533ce6660ca7e50d355fdbe05fed173270 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 13 Nov 2023 09:44:04 +0000 Subject: [PATCH 12/26] Prepare changelog for v30.0.1 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f48d02866..e64e4c848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [30.0.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v30.0.1) (2023-11-13) +================================================================================================== + +## 🐛 Bug Fixes + * Ensure `setUserCreator` is called when a store is assigned ([\#3867](https://github.com/matrix-org/matrix-js-sdk/pull/3867)). Fixes vector-im/element-web#26520. Contributed by @MidhunSureshR. + Changes in [30.0.0](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v30.0.0) (2023-11-07) ================================================================================================== From 430e6cae948ebfa344deb8818c091d57f86fb2dd Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 13 Nov 2023 09:44:06 +0000 Subject: [PATCH 13/26] v30.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbbaf876e..c049a9906 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-js-sdk", - "version": "30.0.0", + "version": "30.0.1", "description": "Matrix Client-Server SDK for Javascript", "engines": { "node": ">=18.0.0" From d179b8c557eeca955d58d43e53d90b8517c2e1e8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Nov 2023 09:46:11 +0000 Subject: [PATCH 14/26] Add automation to advance release blocker labels during the release (#3866) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index a954a425c..f0053a118 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -334,3 +334,20 @@ jobs: uses: matrix-org/matrix-js-sdk/.github/workflows/release-npm.yml@develop secrets: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + update-labels: + name: Advance release blocker labels + needs: release + runs-on: ubuntu-latest + steps: + - id: repository + run: echo "REPO=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV + + - uses: garganshu/github-label-updater@3770d15ebfed2fe2cb06a241047bc340f774a7d1 # v1.0.0 + with: + owner: ${{ github.repository_owner }} + repo: ${{ steps.repository.outputs.REPO }} + token: ${{ secrets.GITHUB_TOKEN }} + filter-labels: X-Upcoming-Release-Blocker + remove-labels: X-Upcoming-Release-Blocker + add-labels: X-Release-Blocker From 7de9b23e5993b62ffb3e24cb2818d7bfca0a67da Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 13 Nov 2023 12:43:18 +0000 Subject: [PATCH 15/26] Add support for ingest-changes to refer to a project without package.json (#3864) * Tidy reusable release workflow Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add ability to include upstream changes Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add ability to upload assets and gpg sign them Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update relative composite actions Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Wire up validating release tarball signature Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Validate release has expected assets Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Paths Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Use gpg outputs for email instead of scraping it ourselves Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * v6 Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Extract pre-release and post-merge-master scripts Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Reuse pre-release and post-merge-master scripts in gha Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Cull unused vars Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove unused variables Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Simplify and fix merge-release-notes script Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Tidy release automation Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update release.sh * Move environment Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * s/includes/contains/ Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate uses syntax Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix action-repo calls Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix RELEASE_NOTES env Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix if check Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix gpg tag signing Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Cull stale params Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix sign-release-tarball paths being outside the workspace Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix gpg validation (of course wget uses `-O` and not `-o`) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix expected asset assertion Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix release publish mode Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add support for ingest-changes to refer to a project without it being in node_modules Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 4 ++-- scripts/release/merge-release-notes.js | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index f0053a118..f6f44ace5 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -193,13 +193,13 @@ jobs: with: retries: 3 script: | - const { RELEASE_ID: releaseId, DEPENDENCY } = process.env; + const { RELEASE_ID: releaseId, DEPENDENCY, VERSION } = process.env; const { owner, repo } = context.repo; const script = require("./.action-repo/scripts/release/merge-release-notes.js"); const notes = await script({ github, releaseId, - dependencies: [DEPENDENCY], + dependencies: [DEPENDENCY.replace("$VERSION", VERSION)], }); core.exportVariable("RELEASE_NOTES", notes); diff --git a/scripts/release/merge-release-notes.js b/scripts/release/merge-release-notes.js index f98aa46e9..0f64f65df 100755 --- a/scripts/release/merge-release-notes.js +++ b/scripts/release/merge-release-notes.js @@ -3,9 +3,18 @@ const fs = require("fs"); async function getRelease(github, dependency) { - const upstreamPackageJson = JSON.parse(fs.readFileSync(`./node_modules/${dependency}/package.json`, "utf8")); - const [owner, repo] = upstreamPackageJson.repository.url.split("/").slice(-2); - const tag = `v${upstreamPackageJson.version}`; + let owner; + let repo; + let tag; + if (dependency.includes("/") && dependency.includes("@")) { + owner = dependency.split("/")[0]; + repo = dependency.split("/")[1].split("@")[0]; + tag = dependency.split("@")[1]; + } else { + const upstreamPackageJson = JSON.parse(fs.readFileSync(`./node_modules/${dependency}/package.json`, "utf8")); + [owner, repo] = upstreamPackageJson.repository.url.split("/").slice(-2); + tag = `v${upstreamPackageJson.version}`; + } const response = await github.rest.repos.getReleaseByTag({ owner, From 25a777a0a6aa998063efc8154f48fac9ace44a2e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 13:41:37 +0000 Subject: [PATCH 16/26] Update release-drafter.yml --- .github/workflows/release-drafter.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 3ce2b5a2a..0820237d8 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -2,13 +2,20 @@ name: Release Drafter on: push: branches: [staging] + workflow_dispatch: + inputs: + previous-version: + description: What release to use as a base for release note purposes + required: false + type: string concurrency: ${{ github.workflow }} jobs: draft: runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@dabcf3767562210392d862070ed2ef6434b9bc6f # v5 + - uses: release-drafter/release-drafter@219b17038f47a488197914b7d8f813de08677fc5 # v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: disable-autolabeler: true + previous-version: ${{ inputs.previous-version }} From c54f8f61067cbb0406e69f5f606e8f4ed4aaa658 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 13:47:56 +0000 Subject: [PATCH 17/26] Update release-drafter.yml --- .github/workflows/release-drafter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 0820237d8..4d889f456 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -13,7 +13,7 @@ jobs: draft: runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@219b17038f47a488197914b7d8f813de08677fc5 # v5 + - uses: release-drafter/release-drafter@e64b19c4c46173209ed9f2e5a2f4ca7de89a0e86 # v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 939def2aa1b77a5e66edc16bcd20e0dd2baf0a33 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 13:51:16 +0000 Subject: [PATCH 18/26] Update release-drafter.yml --- .github/release-drafter.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 462af3942..b8b3d846e 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -19,6 +19,9 @@ version-resolver: labels: - "X-Breaking-Change" default: minor +exclude-labels: + - "T-Task" + - "X-Reverted" template: | $CHANGES prerelease: true From 9044145a7ec393187cca55e3a19465fb5c92b6a1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 14:03:09 +0000 Subject: [PATCH 19/26] Update release-action.yml --- .github/workflows/release-action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index f6f44ace5..aba35db89 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -230,7 +230,7 @@ jobs: run: git commit -m "$VERSION" - name: Build assets - if: steps.prepare.outputs.has-dist-script + if: steps.prepare.outputs.has-dist-script == '1' run: DIST_VERSION="$VERSION" yarn dist - name: Upload release assets & signatures From b9e684fdc3e7ded0a0876db1358ff25ba6faee6d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 14:07:25 +0000 Subject: [PATCH 20/26] Update release-action.yml --- .github/workflows/release-action.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index aba35db89..f767e63c4 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -306,6 +306,7 @@ jobs: FINAL: ${{ inputs.final }} with: retries: 3 + github-token: ${{ secrets.ELEMENT_BOT_TOKEN }} script: | const { RELEASE_ID: release_id, RELEASE_NOTES, VERSION, FINAL } = process.env; const { owner, repo } = context.repo; From eb9e557a6471101eed042756b9d0d286d1b9ea6e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 14:19:52 +0000 Subject: [PATCH 21/26] Update release-action.yml --- .github/workflows/release-action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index f767e63c4..fc35e09b6 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -342,7 +342,7 @@ jobs: runs-on: ubuntu-latest steps: - id: repository - run: echo "REPO=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV + run: echo "REPO=${GITHUB_REPOSITORY#*/}" >> $GITHUB_OUTPUT - uses: garganshu/github-label-updater@3770d15ebfed2fe2cb06a241047bc340f774a7d1 # v1.0.0 with: From a11fd8bc8602ba9c332505b3594f2f72f8064e50 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 15:22:03 +0100 Subject: [PATCH 22/26] release-npm.yml ref=staging Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-npm.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index a41861749..efba1d967 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -11,6 +11,8 @@ jobs: steps: - name: 🧮 Checkout code uses: actions/checkout@v4 + with: + ref: staging - name: 🔧 Yarn cache uses: actions/setup-node@v4 From 48fe267ea7fb5272dcc7a39d303305b9167f2ca9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 15:26:31 +0100 Subject: [PATCH 23/26] release-action.yml iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index fc35e09b6..cfb805c52 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -90,7 +90,7 @@ jobs: echo "VERSION=$VERSION" >> $GITHUB_ENV { echo "RELEASE_NOTES<> $GITHUB_ENV @@ -102,7 +102,7 @@ jobs: VERSION: ${{ steps.release.outputs.tag_name }} - name: Finalise version - if: inputs.mode == 'final' + if: inputs.final run: echo "VERSION=$(echo $VERSION | cut -d- -f1)" >> $GITHUB_ENV - name: Check version number not in use @@ -204,7 +204,7 @@ jobs: core.exportVariable("RELEASE_NOTES", notes); - name: Add to CHANGELOG.md - if: inputs.mode == 'final' + if: inputs.final run: | mv CHANGELOG.md CHANGELOG.md.old HEADER="Changes in [${VERSION#v}](https://github.com/${{ github.repository }}/releases/tag/$VERSION) ($(date '+%Y-%m-%d'))" From 37ba169abfc224035c1d5dc20ec9f26084b4a934 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 14:52:56 +0000 Subject: [PATCH 24/26] Update release-drafter.yml --- .github/release-drafter.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index b8b3d846e..102313bdd 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -22,6 +22,8 @@ version-resolver: exclude-labels: - "T-Task" - "X-Reverted" +exclude-contributors: + - "RiotRobot" template: | $CHANGES prerelease: true From 378a91fe108715b4e29a6a0dd117a65893e33e9a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 16:31:58 +0100 Subject: [PATCH 25/26] Fix yarn version call in release-action.yml Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index cfb805c52..6e1722a63 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -179,7 +179,7 @@ jobs: fi - name: Bump package.json version - run: yarn version --no-git-tag-version --new-version "$VERSION" + run: yarn version --no-git-tag-version --new-version "${VERSION#v}" - name: Ingest upstream changes if: | From 138281c62076e42e000f63fdb0d1f6e68773767f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 14 Nov 2023 17:12:49 +0100 Subject: [PATCH 26/26] Fix RELEASE_ID Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/release-action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-action.yml b/.github/workflows/release-action.yml index 6e1722a63..ea71d3511 100644 --- a/.github/workflows/release-action.yml +++ b/.github/workflows/release-action.yml @@ -188,7 +188,7 @@ jobs: contains(fromJSON(steps.update-dependencies.outputs.updated), inputs.include-changes) uses: actions/github-script@v6 env: - RELEASE_ID: ${{ steps.upstream-release.outputs.body }} + RELEASE_ID: ${{ steps.release.outputs.id }} DEPENDENCY: ${{ inputs.include-changes }} with: retries: 3