bitmovin-player-ui 3.102.0 → 3.102.1-a.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,24 @@
1
+ name: 'Setup Dependencies'
2
+ description: 'Sets up Node.js, caches node modules, and installs dependencies'
3
+
4
+ runs:
5
+ using: 'composite'
6
+ steps:
7
+ - name: Set up node.js
8
+ uses: actions/setup-node@v4
9
+ with:
10
+ node-version-file: .nvmrc
11
+
12
+ - name: Cache node modules
13
+ id: cache-nodemodules
14
+ uses: actions/cache@v4
15
+ env:
16
+ cache-name: cache-node-modules
17
+ with:
18
+ path: node_modules
19
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
20
+
21
+ - name: Install dependencies
22
+ if: steps.cache-nodemodules.outputs.cache-hit != 'true'
23
+ run: npm ci
24
+ shell: bash
@@ -0,0 +1,70 @@
1
+ const semver = require('semver');
2
+
3
+ /**
4
+ * Calculates the full version number based on release type and input version
5
+ *
6
+ * @param {object} core - GitHub Actions core object for logging
7
+ * @param {string} inputVersionNumber - Base version number (e.g., "3.102.1")
8
+ * @param {string} releaseType - Type of release (alpha, beta, rc, final)
9
+ * @param {string} latestTag - Latest existing tag for this version and release type - optional
10
+ * @returns {object} - Returns object with version_number, major_version, and tag_name
11
+ */
12
+ function calculateVersionNumber(core, inputVersionNumber, releaseType, latestTag = '') {
13
+ const isValid = semver.valid(inputVersionNumber);
14
+ if (!isValid) {
15
+ throw new Error(`Invalid version number: ${inputVersionNumber}`);
16
+ }
17
+
18
+ let fullVersion;
19
+ if (releaseType === 'final') {
20
+ fullVersion = inputVersionNumber;
21
+ } else {
22
+ let shortName;
23
+ switch (releaseType) {
24
+ case 'alpha':
25
+ shortName = 'a';
26
+ break;
27
+ case 'beta':
28
+ shortName = 'b';
29
+ break;
30
+ case 'rc':
31
+ shortName = 'rc';
32
+ break;
33
+ default:
34
+ throw new Error(`Invalid release type: ${releaseType}`);
35
+ }
36
+
37
+ let nextNumber = 1;
38
+ if (latestTag) {
39
+ const match = latestTag.match(new RegExp(`^v${inputVersionNumber.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}-${shortName}\\.(\\d+)$`));
40
+ if (match) {
41
+ nextNumber = parseInt(match[1]) + 1;
42
+ }
43
+ }
44
+
45
+ fullVersion = `${inputVersionNumber}-${shortName}.${nextNumber}`;
46
+ core.info(`Short name: ${shortName}, Latest tag: ${latestTag || 'none'}, next number: ${nextNumber}`);
47
+ }
48
+
49
+ const isFullVersionValid = semver.valid(fullVersion);
50
+ if (!isFullVersionValid) {
51
+ throw new Error(`Generated invalid version: ${fullVersion}`);
52
+ }
53
+
54
+ const majorVersion = semver.major(fullVersion);
55
+ const tagName = `v${fullVersion}`;
56
+
57
+ core.info(`Input version: ${inputVersionNumber}`);
58
+ core.info(`Release type: ${releaseType}`);
59
+ core.info(`Full version: ${fullVersion}`);
60
+ core.info(`Major version: ${majorVersion}`);
61
+ core.info(`Tag name: ${tagName}`);
62
+
63
+ return {
64
+ version_number: fullVersion,
65
+ major_version: majorVersion,
66
+ tag_name: tagName
67
+ };
68
+ }
69
+
70
+ module.exports.calculateVersionNumber = calculateVersionNumber;
@@ -0,0 +1,46 @@
1
+ const fs = require('fs');
2
+
3
+ /**
4
+ * Detects the release level (minor or patch) based on changelog content
5
+ *
6
+ * @param {object} core - GitHub Actions core object for logging
7
+ * @param {string} changelogPath - Path to the changelog file (defaults to './CHANGELOG.md')
8
+ * @returns {string} - Returns 'minor' or 'patch'
9
+ */
10
+ function detectReleaseLevel(core, changelogPath = './CHANGELOG.md') {
11
+ const changelogContent = fs.readFileSync(changelogPath, { encoding: 'utf8', flag: 'r' });
12
+
13
+ const unreleasedMatch = changelogContent.match(/## \[?unreleased\]?/i);
14
+ if (!unreleasedMatch) {
15
+ throw new Error('No unreleased section found in CHANGELOG.md');
16
+ }
17
+
18
+ const unreleasedStart = unreleasedMatch.index + unreleasedMatch[0].length;
19
+ const nextSectionMatch = changelogContent.substring(unreleasedStart).match(/^## /m);
20
+ const unreleasedEnd = nextSectionMatch ? unreleasedStart + nextSectionMatch.index : changelogContent.length;
21
+ const unreleasedContent = changelogContent.substring(unreleasedStart, unreleasedEnd);
22
+
23
+ core.info('Unreleased section content:');
24
+ core.info(unreleasedContent);
25
+
26
+ const hasAdded = /### added/i.test(unreleasedContent);
27
+ const hasChanged = /### changed/i.test(unreleasedContent);
28
+ const hasRemoved = /### removed/i.test(unreleasedContent);
29
+ const hasFixed = /### fixed/i.test(unreleasedContent);
30
+
31
+ let releaseLevel;
32
+ if (hasAdded || hasChanged || hasRemoved) {
33
+ releaseLevel = 'minor';
34
+ core.info('Found Added, Changed, or Removed sections - will create minor release');
35
+ } else if (hasFixed) {
36
+ releaseLevel = 'patch';
37
+ core.info('Found only Fixed sections - will create patch release');
38
+ } else {
39
+ throw new Error('No valid changelog entries found in unreleased section');
40
+ }
41
+
42
+ core.info(`Release level: ${releaseLevel}`);
43
+ return releaseLevel;
44
+ }
45
+
46
+ module.exports.detectReleaseLevel = detectReleaseLevel;
@@ -1,10 +1,11 @@
1
1
  const fs = require('fs');
2
2
  const https = require('https');
3
3
 
4
- const jobStatus = process.argv[2];
5
- const changelogPath = process.argv[3];
6
- const slackWebhookUrl = process.argv[4];
7
- const runId = process.argv[5];
4
+ const versionNumber = process.argv[2];
5
+ const jobStatus = process.argv[3];
6
+ const changelogPath = process.argv[4];
7
+ const slackWebhookUrl = process.argv[5];
8
+ const runId = process.argv[6];
8
9
 
9
10
  const failureSlackChannelId = 'CGRK9DV7H';
10
11
  const successSlackChannelId = 'C0LJ16JBS';
@@ -15,16 +16,9 @@ fs.readFile(changelogPath, 'utf8', (err, fileContent) => {
15
16
  }
16
17
 
17
18
  const changelogContent = parseChangelogEntry(fileContent);
18
- const releaseVersion = parseReleaseVersion(fileContent);
19
- sendSlackMessage(releaseVersion, changelogContent);
19
+ sendSlackMessage(versionNumber, changelogContent);
20
20
  });
21
21
 
22
- function parseReleaseVersion(fileContent) {
23
- const regex = /##\s\[(\d+\.\d+.\d+)\]/;
24
- const releaseVersion = fileContent.match(regex);
25
-
26
- return releaseVersion[1];
27
- }
28
22
 
29
23
  function parseChangelogEntry(fileContent) {
30
24
  // The regex looks for the first paragraph starting with "###" until it finds
@@ -39,20 +33,53 @@ function parseChangelogEntry(fileContent) {
39
33
  }
40
34
 
41
35
  function sendSlackMessage(releaseVersion, changelogContent) {
42
- let message;
43
- let slackChannelId;
36
+ const slackChannelId = jobStatus === 'success' ? successSlackChannelId : failureSlackChannelId;
37
+ const generalPayload = {
38
+ channel: slackChannelId
39
+ };
40
+
41
+ let payload;
44
42
  if (jobStatus === 'success') {
45
- slackChannelId = successSlackChannelId
46
- message = `Changelog v${releaseVersion}\n${changelogContent}`
43
+ payload = {
44
+ ...generalPayload,
45
+ text: `New Bitmovin Player UI version is released!`,
46
+ attachments: [
47
+ {
48
+ title: `CHANGELOG v${releaseVersion}`,
49
+ color: '#0e7aff',
50
+ fallback: 'Changelog of the newest release should be displayed here',
51
+ text: changelogContent,
52
+ fields: [
53
+ {
54
+ title: 'Version',
55
+ value: `v${releaseVersion}`,
56
+ short: true,
57
+ },
58
+ {
59
+ title: 'Channel',
60
+ value: releaseVersion.includes('-') ? 'pre-release' : 'release',
61
+ short: true,
62
+ },
63
+ ],
64
+ },
65
+ ],
66
+ }
47
67
  } else {
48
- slackChannelId = failureSlackChannelId
49
- message = `Release v${releaseVersion} failed.\nPlease check https://github.com/bitmovin/bitmovin-player-ui/actions/runs/${runId}`
68
+ payload = {
69
+ ...generalPayload,
70
+ text: `<!subteam^S06RHTF937F> Release *v${releaseVersion}* failed.`,
71
+ attachments: [
72
+ {
73
+ title: `Release Failure`,
74
+ color: '#ff0000',
75
+ fallback: 'Release failed',
76
+ text: `Please check the <https://github.com/bitmovin/bitmovin-player-ui/actions/runs/${runId}|failed run>`,
77
+ },
78
+ ],
79
+ }
50
80
  }
51
81
 
52
- const sampleData = JSON.stringify({
53
- "channel": slackChannelId,
54
- "message": message
55
- });
82
+ const sampleData = JSON.stringify(payload);
56
83
  const options = {
57
84
  method: 'POST',
58
85
  headers: {
@@ -5,51 +5,47 @@ on:
5
5
  branches:
6
6
  - '**'
7
7
 
8
- workflow_dispatch:
9
-
10
8
  workflow_call:
11
9
 
12
10
  jobs:
13
- test_and_build:
11
+ test:
12
+ name: Test
14
13
  runs-on: ubuntu-latest
15
14
 
16
15
  steps:
17
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
18
16
  - name: Checkout
19
17
  uses: actions/checkout@v4
20
18
 
21
- - name: Set up node.js
22
- uses: actions/setup-node@v4
23
- with:
24
- node-version-file: .nvmrc
25
-
26
- - name: Cache node modules
27
- id: cache-nodemodules
28
- uses: actions/cache@v4
29
- env:
30
- cache-name: cache-node-modules
31
- with:
32
- path: node_modules
33
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
34
-
35
- - name: Install dependencies
36
- if: steps.cache-nodemodules.outputs.cache-hit != 'true'
37
- run: npm ci
19
+ - name: Setup dependencies
20
+ uses: ./.github/actions/setup-dependencies
38
21
 
39
22
  - name: Test
40
23
  run: npm test
41
24
 
42
- - name: Build and prepare for a potential 'npm publish'
43
- run: gulp npm-prepare
25
+ build:
26
+ name: Build
27
+ runs-on: ubuntu-latest
28
+
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v4
44
32
 
45
- - name: Package artifact for upload
46
- run: tar -czvf artifact.tar.gz dist
47
- shell: bash
33
+ - name: Setup dependencies
34
+ uses: ./.github/actions/setup-dependencies
35
+
36
+ - name: Build
37
+ run: npx gulp build
38
+
39
+ lint:
40
+ name: Lint
41
+ runs-on: ubuntu-latest
42
+
43
+ steps:
44
+ - name: Checkout
45
+ uses: actions/checkout@v4
48
46
 
49
- - uses: actions/upload-artifact@v4
50
- with:
51
- path: |
52
- ${{ github.workspace }}/artifact.tar.gz
53
- if-no-files-found: error
54
- retention-days: 1
47
+ - name: Setup dependencies
48
+ uses: ./.github/actions/setup-dependencies
55
49
 
50
+ - name: Lint
51
+ run: npx gulp lint
@@ -1,51 +1,189 @@
1
1
  name: Release
2
-
3
- on:
4
- push:
5
- tags:
6
- - '!player/'
7
- - 'v*'
2
+ run-name: Release ${{ inputs.version_number }} ${{ inputs.release_type }}
3
+
4
+ on:
5
+ # For manually triggered workflows
6
+ workflow_dispatch:
7
+ inputs:
8
+ version_number:
9
+ description: "Version number of the release (no `v` prefix and no `-rc.`, `-b.`, `-a.` suffix)"
10
+ type: string
11
+ required: true
12
+ release_type:
13
+ description: Select the type of the release
14
+ type: choice
15
+ options:
16
+ - alpha
17
+ - beta
18
+ - rc
19
+ - final
20
+ required: true
21
+
22
+ # For being called by other workflows
23
+ workflow_call:
24
+ inputs:
25
+ version_number:
26
+ description: "Version number of the release (no `v` prefix and no `-rc.`, `-b.`, `-a.` suffix)"
27
+ type: string
28
+ required: true
29
+ release_type:
30
+ description: Select the type of the release
31
+ type: string
32
+ required: true
33
+ branch_name:
34
+ description: Branch from which the release should be built. Useful when another workflow calls this one.
35
+ type: string
36
+ required: true
37
+ secrets:
38
+ NPM_AUTH_TOKEN:
39
+ description: 'NPM authentication token for publishing'
40
+ required: true
41
+ GCS_CREDENTIALS:
42
+ description: 'Google Cloud Storage credentials for uploading docs'
43
+ required: true
44
+ SLACK_WEBHOOK_URL:
45
+ description: 'Slack webhook URL for notifications'
46
+ required: true
8
47
 
9
48
  jobs:
10
- test_and_build:
11
- uses: ./.github/workflows/ci.yml
12
-
13
- download_and_publish:
14
- needs: test_and_build
49
+ version_bump:
50
+ name: Version Bump
15
51
  runs-on: ubuntu-latest
16
-
52
+ outputs:
53
+ major_version: ${{ steps.version_number.outputs.major_version }}
54
+ version_number: ${{ steps.version_number.outputs.version_number }}
55
+ tag_name: ${{ steps.version_number.outputs.tag_name }}
17
56
  steps:
18
- - name: Checkout
19
- uses: actions/checkout@v4
57
+ - uses: actions/checkout@v4
20
58
  with:
21
- ref: develop
22
-
23
- - name: Install dependencies
24
- run: npm ci
59
+ ref: ${{ inputs.branch_name || github.ref }}
60
+ # Fetch existing tags because we need to create a new one
61
+ # fetch-tags: true # do not use, currently broken: https://github.com/actions/checkout/issues/1781
62
+ fetch-depth: 0 # remove this line when `fetch-tags: true` is fixed
63
+
64
+ - name: Setup dependencies
65
+ uses: ./.github/actions/setup-dependencies
66
+
67
+ - name: Get latest pre-release tag
68
+ id: latest_tag
69
+ if: inputs.release_type != 'final'
70
+ run: |
71
+ case "${{ inputs.release_type }}" in
72
+ "alpha")
73
+ short_name="a"
74
+ ;;
75
+ "beta")
76
+ short_name="b"
77
+ ;;
78
+ "rc")
79
+ short_name="rc"
80
+ ;;
81
+ *)
82
+ echo "Invalid release type"
83
+ exit 1
84
+ ;;
85
+ esac
86
+
87
+ latest_tag=$(git tag --list "v${{ inputs.version_number }}-$short_name.*" | sort -V -r | head -n1 || echo "")
88
+ echo "latest_tag=$latest_tag" >> $GITHUB_OUTPUT
89
+
90
+ - name: Calculate version number
91
+ uses: actions/github-script@v6
92
+ id: version_number
93
+ with:
94
+ script: |
95
+ const { calculateVersionNumber } = require('./.github/scripts/calculateVersionNumber.js');
96
+
97
+ const inputVersionNumber = '${{ inputs.version_number }}';
98
+ const releaseType = '${{ inputs.release_type }}';
99
+ const latestTag = '${{ steps.latest_tag.outputs.latest_tag }}';
100
+
101
+ try {
102
+ const result = calculateVersionNumber(core, inputVersionNumber, releaseType, latestTag);
103
+
104
+ core.setOutput('version_number', result.version_number);
105
+ core.setOutput('major_version', result.major_version);
106
+ core.setOutput('tag_name', result.tag_name);
107
+ } catch (error) {
108
+ core.setFailed(error.message);
109
+ }
110
+
111
+ - name: Bump version in package.json
112
+ run: |
113
+ npm version "${{ steps.version_number.outputs.version_number }}" --no-git-tag-version
114
+ shell: bash
25
115
 
26
- - name: Read package.json version
116
+ - name: Update changelog
117
+ if: inputs.release_type == 'final'
27
118
  uses: actions/github-script@v6
28
- id: extract-version
29
119
  with:
30
120
  script: |
31
- const { version } = require('./package.json')
32
- core.setOutput('packageJsonVersion', version)
121
+ const fs = require('fs');
122
+ const { updateChangeLog } = require('./.github/scripts/updateChangelog.js');
123
+
124
+ const versionNumber = '${{ steps.version_number.outputs.version_number }}';
125
+ const releaseDate = new Date().toISOString().split('T')[0];
126
+
127
+ core.info(`Updating changelog with version ${versionNumber} and date ${releaseDate}`);
128
+
129
+ const changelogContent = fs.readFileSync('./CHANGELOG.md', { encoding: 'utf8', flag: 'r' });
130
+ const updatedChangelog = updateChangeLog(changelogContent, versionNumber, releaseDate);
131
+
132
+ fs.writeFileSync('./CHANGELOG.md', updatedChangelog, 'utf-8');
133
+ core.info('Changelog updated successfully');
134
+
135
+ - name: Commit and tag the changes
136
+ run: |
137
+ git config --global user.name 'Automated Release'
138
+ git config --global user.email 'release-automation@bitmovin.com'
139
+ git add package.json CHANGELOG.md
140
+ git commit -m "Bump version to ${{ steps.version_number.outputs.version_number }}"
141
+ git tag "${{ steps.version_number.outputs.tag_name }}"
142
+ git push origin ${{ inputs.branch_name || github.ref_name }}
143
+ git push origin "${{ steps.version_number.outputs.tag_name }}"
144
+
145
+ test:
146
+ needs: version_bump
147
+ name: Test, Build and Lint
148
+ uses: ./.github/workflows/ci.yml
33
149
 
34
- - uses: actions/download-artifact@v4
150
+ release:
151
+ name: Publish Release
152
+ needs: [test, version_bump]
153
+ runs-on: ubuntu-latest
154
+ steps:
155
+ - name: Checkout
156
+ uses: actions/checkout@v4
35
157
  with:
36
- path: .
158
+ ref: ${{ needs.version_bump.outputs.tag_name }}
159
+
160
+ - name: Setup dependencies
161
+ uses: ./.github/actions/setup-dependencies
37
162
 
38
- - name: Unpackage artifact files
39
- run: tar -xzvf artifact/artifact.tar.gz -C .
163
+ - name: Build Release
164
+ run: npx gulp npm-prepare
40
165
  shell: bash
41
166
 
42
- - name: Publish
43
- run: ./publish.sh
167
+ - name: Publish to NPM
168
+ run: ./publish.sh --version "${{ needs.version_bump.outputs.version_number }}"
44
169
  shell: bash
45
170
  env:
46
171
  NPM_DRY_RUN: false
47
172
  NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
48
173
 
174
+ upload_docs:
175
+ name: Upload Documentation
176
+ needs: [test, version_bump, release]
177
+ runs-on: ubuntu-latest
178
+ steps:
179
+ - name: Checkout
180
+ uses: actions/checkout@v4
181
+ with:
182
+ ref: ${{ needs.version_bump.outputs.tag_name }}
183
+
184
+ - name: Setup dependencies
185
+ uses: ./.github/actions/setup-dependencies
186
+
49
187
  - name: Build documentation
50
188
  run: npx typedoc
51
189
  shell: bash
@@ -59,26 +197,37 @@ jobs:
59
197
  uses: 'google-github-actions/upload-cloud-storage@v2'
60
198
  with:
61
199
  path: './docs/'
62
- destination: "${{ secrets.GCS_BUCKET }}/player/ui/${{ steps.extract-version.outputs.packageJsonVersion }}"
200
+ destination: "${{ secrets.GCS_BUCKET }}/player/ui/${{ needs.version_bump.outputs.version_number }}"
63
201
 
64
202
  - name: Upload docs for major version
65
203
  uses: 'google-github-actions/upload-cloud-storage@v2'
66
204
  with:
67
205
  path: './docs/'
68
- destination: "${{ secrets.GCS_BUCKET }}/player/ui/3"
206
+ destination: "${{ secrets.GCS_BUCKET }}/player/ui/${{ needs.version_bump.outputs.major_version }}"
207
+
208
+ notify_success:
209
+ name: Notify Success
210
+ needs: [test, version_bump, release, upload_docs]
211
+ runs-on: ubuntu-latest
212
+ steps:
213
+ - name: Checkout
214
+ uses: actions/checkout@v4
215
+ with:
216
+ ref: ${{ needs.version_bump.outputs.tag_name }}
69
217
 
70
218
  - name: Notify team
71
- run: node .github/scripts/notifySlackTeam.js 'success' 'CHANGELOG.md' ${{ secrets.RELEASE_SUCCESS_SLACK_WEBHOOK }}
219
+ run: node .github/scripts/notifySlackTeam.js ${{ needs.version_bump.outputs.version_number }} 'success' 'CHANGELOG.md' ${{ secrets.SLACK_WEBHOOK_URL }}
72
220
 
73
221
  handle_failure:
222
+ name: Handle Failure
74
223
  runs-on: ubuntu-latest
75
- needs: [test_and_build, download_and_publish]
76
- if: ${{ always() && (needs.download_and_publish.result == 'failure' || needs.test_and_build.result == 'failure') }}
224
+ needs: [test, version_bump, release, upload_docs, notify_success]
225
+ if: ${{ always() && (needs.test.result == 'failure' || needs.version_bump.result == 'failure' || needs.release.result == 'failure' || needs.upload_docs.result == 'failure' || needs.notify_success.result == 'failure') }}
77
226
  steps:
78
227
  - name: Checkout
79
228
  uses: actions/checkout@v4
80
229
  with:
81
- ref: develop
230
+ ref: ${{ needs.version_bump.outputs.tag_name }}
82
231
 
83
232
  - name: Notify team
84
- run: node .github/scripts/notifySlackTeam.js 'failure' 'CHANGELOG.md' ${{ secrets.RELEASE_FAILURE_SLACK_WEBHOOK }} ${{ github.run_id }}
233
+ run: node .github/scripts/notifySlackTeam.js ${{ needs.version_bump.outputs.version_number }} 'failure' 'CHANGELOG.md' ${{ secrets.SLACK_WEBHOOK_URL }} ${{ github.run_id }}