Repository navigation
PFM-ISSUE-34283 - Consolidate the FE 2.0 release flow into a single workflow #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,22 @@ | ||
| name: 'Frontend Artifacts Handler Action' | ||
| description: 'Github Action to handle frontend artifacts' | ||
| outputs: | ||
| tag: | ||
| description: 'The pushed version tag, set only once the version is published and tagged (release flow only)' | ||
| value: ${{ steps.handler.outputs.tag }} | ||
| previous_tag: | ||
| description: 'The previous tag of the same release line, empty for X.Y.1 (release flow only)' | ||
| value: ${{ steps.handler.outputs.previous_tag }} | ||
| is_latest: | ||
| description: 'true if the pushed tag is the highest version/* tag (release flow only)' | ||
| value: ${{ steps.handler.outputs.is_latest }} | ||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - run: printenv | ||
| shell: bash | ||
| - run: cd "$GITHUB_ACTION_PATH/../../.." && pwd && npm ci | ||
| shell: bash | ||
| - run: npx ts-node "$GITHUB_ACTION_PATH/../../../tools/scripts/artifacts/main.ts" | ||
| - id: handler | ||
| run: npx ts-node "$GITHUB_ACTION_PATH/../../../tools/scripts/artifacts/main.ts" | ||
| shell: bash |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,53 +1,32 @@ | ||
| # Replaces the old two-file release (this file as tagger + fe-tag-pushed.yml / on_tag_pushed.yaml / tag_pushed.yml). | ||
| # Delete BOTH old caller files in the same commit that adds this one: the release flow still pushes | ||
| # the tag with the PAT, so a tag-push workflow left in the tree would publish that tag again (and | ||
| # release manually pushed tags). The release flow's guard job fails while an old caller exists. | ||
| # PFM-ISSUE-34282 (pushing the tag with GITHUB_TOKEN) removes the tag-push trigger for good. | ||
| name: 'Frontend Release CI' | ||
| on: | ||
| push: | ||
| branches: | ||
| - 'release/*' | ||
| workflow_dispatch: | ||
| inputs: | ||
| force: | ||
| description: 'Tag and publish (release/*) or publish a snapshot of all projects (default branch). Unticked: build and test only, nothing is tagged or published.' | ||
| type: boolean | ||
| default: false | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| actions: read | ||
| checks: write | ||
|
|
||
| env: | ||
| NX_BRANCH: ${{ github.event.number }} | ||
| NX_RUN_GROUP: ${{ github.run_id }} | ||
| # one release run per branch at a time; a running release is never cancelled | ||
| concurrency: | ||
| group: fe-release-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| install-deps: | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-install-deps.yml@master | ||
| release-flow: | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-release-flow.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| secrets: | ||
| DOT_NPMRC: ${{ secrets.DOT_NPMRC }} | ||
|
|
||
| e2e-tests: | ||
| needs: install-deps | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-e2e.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| GHA_BASE: ${{ github.event.before }} | ||
| secrets: | ||
| PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} | ||
|
|
||
| build: | ||
| needs: install-deps | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-build.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| GHA_BASE: ${{ github.event.before }} | ||
|
|
||
| tag: | ||
| needs: [build, e2e-tests] | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-tag.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| GHA_BASE: ${{ github.event.before }} | ||
| secrets: | ||
| JFROG_BASE64_TOKEN: ${{ secrets.JFROG_BASE64_TOKEN }} | ||
| JFROG_URL: ${{ secrets.JFROG_URL }} | ||
| JFROG_USER: ${{ secrets.JFROG_USER }} | ||
| GIT_USER_TOKEN: ${{ secrets.GIT_USER_TOKEN }} | ||
| GIT_USER: ${{ secrets.GIT_USER }} | ||
| GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }} | ||
| FORCE: ${{ inputs.force == true }} | ||
| # RUN_E2E: false # only for repos that do not run e2e before a release | ||
| secrets: inherit | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,9 +13,6 @@ on: | |
| jobs: | ||
| install-deps: | ||
| runs-on: ubuntu-latest | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❓ Without group: fe-install-deps-${{ github.workflow }}-${{ github.ref }}🤖
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Intended to keep |
||
| concurrency: | ||
| group: fe-install-deps-${{ github.ref }} | ||
| cancel-in-progress: true | ||
| steps: | ||
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||
| with: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,212 @@ | ||
| name: Frontend Release Flow Workflow | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| FORCE: | ||
| description: 'release/*: release even if no project is affected. Default branch: publish a snapshot of all projects. false: build and test only.' | ||
| type: boolean | ||
| required: false | ||
| default: false | ||
| RUN_E2E: | ||
| type: boolean | ||
| required: false | ||
| default: true | ||
| secrets: | ||
| JFROG_BASE64_TOKEN: | ||
| required: true | ||
| JFROG_URL: | ||
| required: true | ||
| JFROG_USER: | ||
| required: true | ||
| DOT_NPMRC: | ||
| required: true | ||
| GIT_USER_TOKEN: | ||
| required: true | ||
| GIT_USER: | ||
| required: true | ||
| GIT_USER_EMAIL: | ||
| required: true | ||
| PERCY_TOKEN: | ||
| required: false | ||
|
|
||
| env: | ||
| NX_BRANCH: ${{ github.event.number }} | ||
| NX_RUN_GROUP: ${{ github.run_id }} | ||
|
|
||
| jobs: | ||
| guard: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - name: Check dispatch ref | ||
| env: | ||
| EVENT_NAME: ${{ github.event_name }} | ||
| REF: ${{ github.ref }} | ||
| DEFAULT_REF: refs/heads/${{ github.event.repository.default_branch }} | ||
| run: | | ||
| if [ "$EVENT_NAME" = "workflow_dispatch" ] && [ "$REF" != "$DEFAULT_REF" ] && [[ "$REF" != refs/heads/release/* ]]; then | ||
| echo "::error::The release flow can only be dispatched on the default branch or a release/* branch, not on $REF" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||
| with: | ||
| sparse-checkout: .github/workflows | ||
| persist-credentials: false | ||
|
|
||
| # an old tag-push caller would publish manually pushed tags and fail on the tags of this flow | ||
| - name: Check for old release callers | ||
| run: | | ||
| old=$(grep -lE 'github-actions/\.github/workflows/(fe-release|fe-tag)\.yml@' .github/workflows/*.y*ml 2> /dev/null || true) | ||
| if [ -n "$old" ]; then | ||
| echo "::error::Old release callers found: $(echo $old). Delete them in the same commit that adds the fe-release-flow caller (see 'FE Release Flow' in the github-actions README)." | ||
| exit 1 | ||
| fi | ||
|
|
||
| install-deps: | ||
| needs: guard | ||
| permissions: | ||
| contents: read | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-install-deps.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| secrets: | ||
| DOT_NPMRC: ${{ secrets.DOT_NPMRC }} | ||
|
|
||
| build: | ||
| needs: install-deps | ||
| permissions: | ||
| contents: read | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-build.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| GHA_BASE: ${{ github.event.before }} | ||
|
|
||
| e2e: | ||
| needs: install-deps | ||
| if: inputs.RUN_E2E | ||
| permissions: | ||
| contents: read | ||
| uses: collaborationFactory/github-actions/.github/workflows/fe-e2e.yml@master | ||
| with: | ||
| GHA_REF: '' | ||
| GHA_BASE: ${{ github.event.before }} | ||
| secrets: | ||
| PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }} | ||
|
|
||
| release: | ||
| needs: [build, e2e] | ||
| # a skipped e2e (RUN_E2E: false) must not skip the release; a non-forced dispatch is a dry run | ||
| if: >- | ||
| !cancelled() | ||
| && needs.build.result == 'success' | ||
| && (needs.e2e.result == 'success' || needs.e2e.result == 'skipped') | ||
| && (github.event_name == 'push' || inputs.FORCE) | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| outputs: | ||
| tag: ${{ steps.release.outputs.tag }} | ||
| previous_tag: ${{ steps.release.outputs.previous_tag }} | ||
| is_latest: ${{ steps.release.outputs.is_latest }} | ||
| steps: | ||
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||
| with: | ||
| ref: '' | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GIT_USER_TOKEN }} | ||
|
|
||
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | ||
| with: | ||
| node-version: 24.20.0 | ||
|
|
||
| - name: Cache Node Modules | ||
| id: npm-cache | ||
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 | ||
| with: | ||
| path: '**/node_modules' | ||
| key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} | ||
|
|
||
| - name: Use .npmrc | ||
| uses: collaborationFactory/github-actions/.github/actions/use-npmrc@master | ||
| with: | ||
| dot-npmrc: ${{ secrets.DOT_NPMRC }} | ||
|
|
||
| - name: Install Modules | ||
| if: steps.npm-cache.outputs.cache-hit != 'true' | ||
| run: npm ci | ||
|
|
||
| - name: Configure git user | ||
| env: | ||
| GIT_USER: ${{ secrets.GIT_USER }} | ||
| GIT_USER_EMAIL: ${{ secrets.GIT_USER_EMAIL }} | ||
| run: | | ||
| git config user.name "$GIT_USER" | ||
| git config user.email "$GIT_USER_EMAIL" | ||
|
|
||
| - name: Publish to Jfrog NPM Registry and Tag | ||
| id: release | ||
| uses: collaborationFactory/github-actions/.github/actions/artifacts@master | ||
| env: | ||
| JFROG_BASE64_TOKEN: ${{ secrets.JFROG_BASE64_TOKEN }} | ||
| JFROG_URL: ${{ secrets.JFROG_URL }} | ||
| JFROG_USER: ${{ secrets.JFROG_USER }} | ||
| RELEASE_FLOW: true | ||
| FORCE: ${{ inputs.FORCE }} | ||
|
|
||
| # the release step writes the version before publishing; once the tag is pushed | ||
| # the release is complete and must not be unpublished | ||
| - name: Check for an incomplete release | ||
| id: incomplete | ||
| if: failure() || cancelled() | ||
| run: | | ||
| file="$RUNNER_TEMP/fe-release-version" | ||
| if [ ! -f "$file" ]; then | ||
| echo "Publishing did not start, nothing to clean up" | ||
| exit 0 | ||
| fi | ||
| tag=$(cat "$file") | ||
| if git ls-remote --exit-code --tags origin "refs/tags/$tag" > /dev/null; then | ||
| echo "$tag is already pushed, the release is complete: nothing to clean up" | ||
| exit 0 | ||
| fi | ||
| echo "$tag was not pushed: unpublishing its artifacts" | ||
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Unpublish the incomplete release | ||
| if: (failure() || cancelled()) && steps.incomplete.outputs.tag != '' | ||
| uses: collaborationFactory/github-actions/.github/actions/artifacts@master | ||
| env: | ||
| JFROG_BASE64_TOKEN: ${{ secrets.JFROG_BASE64_TOKEN }} | ||
| JFROG_URL: ${{ secrets.JFROG_URL }} | ||
| JFROG_USER: ${{ secrets.JFROG_USER }} | ||
| ONLY_DELETE_ARTIFACTS: true | ||
| TAG: ${{ steps.incomplete.outputs.tag }} | ||
|
|
||
| github-release: | ||
| needs: release | ||
| # the tag is set only once the version is published and tagged | ||
| if: needs.release.outputs.tag != '' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: Create GitHub release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| GH_REPO: ${{ github.repository }} | ||
| TAG: ${{ needs.release.outputs.tag }} | ||
| PREVIOUS_TAG: ${{ needs.release.outputs.previous_tag }} | ||
| IS_LATEST: ${{ needs.release.outputs.is_latest }} | ||
| run: | | ||
| if gh release view "$TAG" > /dev/null 2>&1; then | ||
| echo "A GitHub release for $TAG already exists, nothing to do" | ||
| exit 0 | ||
| fi | ||
| args=(--verify-tag --generate-notes "--latest=$IS_LATEST") | ||
| if [ -n "$PREVIOUS_TAG" ]; then | ||
| args+=(--notes-start-tag "$PREVIOUS_TAG") | ||
| fi | ||
| gh release create "$TAG" "${args[@]}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consumers with an old tag-push caller publish twice, and manual tags still release, with only this comment as protection. Please add a migration check, mark the old workflows as deprecated, and link PFM-ISSUE-34282. 🤖
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, all three:
guardnow sparse-checks out.github/workflowsand fails while any workflow still callsworkflows/fe-release.yml@orworkflows/fe-tag.yml@fe-tag.ymlandworkflows/fe-release.ymlprint a::warning::deprecation notice on every run (behavior unchanged)With publish before tag, a leftover tag-push caller can no longer publish twice (it would fail with E403), but the guard now blocks the half-migrated state up front.