pipecraft 0.0.0-releaseit

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.
Files changed (176) hide show
  1. package/.claude/settings.local.json +35 -0
  2. package/.github/actions/calculate-version/action.yml +106 -0
  3. package/.github/actions/create-pr/action.yml +122 -0
  4. package/.github/actions/create-release/action.yml +74 -0
  5. package/.github/actions/create-tag/action.yml +94 -0
  6. package/.github/actions/detect-changes/action.yml +62 -0
  7. package/.github/actions/manage-branch/action.yml +113 -0
  8. package/.github/actions/promote-branch/action.yml +352 -0
  9. package/.github/example/workflows/job.analyze.code.yml +26 -0
  10. package/.github/example/workflows/job.analyze.docker.yml +32 -0
  11. package/.github/example/workflows/job.app.api.deploy.yml +127 -0
  12. package/.github/example/workflows/job.app.api.test.yml +102 -0
  13. package/.github/example/workflows/job.app.docs.deploy.yml +40 -0
  14. package/.github/example/workflows/job.app.docs.test.yml +50 -0
  15. package/.github/example/workflows/job.app.web.deploy.yml +96 -0
  16. package/.github/example/workflows/job.app.web.test.yml +49 -0
  17. package/.github/example/workflows/job.changes.yml +82 -0
  18. package/.github/example/workflows/job.create-pr.yml +96 -0
  19. package/.github/example/workflows/job.env-check.yml +43 -0
  20. package/.github/example/workflows/job.fast-forward.yml +103 -0
  21. package/.github/example/workflows/job.lint.yml +64 -0
  22. package/.github/example/workflows/job.pr-name.yml +70 -0
  23. package/.github/example/workflows/job.pr-squash-name.yml +27 -0
  24. package/.github/example/workflows/job.tag.yml +38 -0
  25. package/.github/example/workflows/job.version.yml +99 -0
  26. package/.github/example/workflows/lib.plugin-base.publish.yml +59 -0
  27. package/.github/example/workflows/pipe.yml +178 -0
  28. package/.github/example/workflows/scripts/fastforward.sh +51 -0
  29. package/.github/example/workflows/scripts/pipe-cleaner.sh +70 -0
  30. package/.github/scripts/fastforward.sh +51 -0
  31. package/.github/scripts/pipe-cleaner.sh +70 -0
  32. package/.github/workflows/pipeline.yml +220 -0
  33. package/.github/workflows/pr-title-check.yml +70 -0
  34. package/.github/workflows/publish.yml +39 -0
  35. package/.pipecraftrc.json +78 -0
  36. package/.release-it.cjs +71 -0
  37. package/PIPELINE_TESTING_PLAN.md +499 -0
  38. package/README.md +1101 -0
  39. package/TRUNK_FLOW_PLAN.md +401 -0
  40. package/assets/logo_banner.png +0 -0
  41. package/assets/logo_banner.webp +0 -0
  42. package/dist/cli/index.d.ts +3 -0
  43. package/dist/cli/index.d.ts.map +1 -0
  44. package/dist/cli/index.js +364 -0
  45. package/dist/cli/index.js.map +1 -0
  46. package/dist/generators/init.tpl.d.ts +3 -0
  47. package/dist/generators/init.tpl.d.ts.map +1 -0
  48. package/dist/generators/init.tpl.js +117 -0
  49. package/dist/generators/init.tpl.js.map +1 -0
  50. package/dist/generators/workflows.tpl.d.ts +7 -0
  51. package/dist/generators/workflows.tpl.d.ts.map +1 -0
  52. package/dist/generators/workflows.tpl.js +73 -0
  53. package/dist/generators/workflows.tpl.js.map +1 -0
  54. package/dist/templates/actions/calculate-version.yml.tpl.d.ts +3 -0
  55. package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -0
  56. package/dist/templates/actions/calculate-version.yml.tpl.js +122 -0
  57. package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -0
  58. package/dist/templates/actions/create-pr.yml.tpl.d.ts +3 -0
  59. package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -0
  60. package/dist/templates/actions/create-pr.yml.tpl.js +145 -0
  61. package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -0
  62. package/dist/templates/actions/create-tag.yml.tpl.d.ts +3 -0
  63. package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -0
  64. package/dist/templates/actions/create-tag.yml.tpl.js +111 -0
  65. package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -0
  66. package/dist/templates/actions/detect-changes.yml.tpl.d.ts +3 -0
  67. package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -0
  68. package/dist/templates/actions/detect-changes.yml.tpl.js +79 -0
  69. package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -0
  70. package/dist/templates/actions/manage-branch.yml.tpl.d.ts +3 -0
  71. package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -0
  72. package/dist/templates/actions/manage-branch.yml.tpl.js +130 -0
  73. package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -0
  74. package/dist/templates/actions/promote-branch.yml.tpl.d.ts +3 -0
  75. package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -0
  76. package/dist/templates/actions/promote-branch.yml.tpl.js +362 -0
  77. package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -0
  78. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +16 -0
  79. package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -0
  80. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +652 -0
  81. package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -0
  82. package/dist/types/index.d.ts +63 -0
  83. package/dist/types/index.d.ts.map +1 -0
  84. package/dist/types/index.js +2 -0
  85. package/dist/types/index.js.map +1 -0
  86. package/dist/utils/ast-path-operations.d.ts +287 -0
  87. package/dist/utils/ast-path-operations.d.ts.map +1 -0
  88. package/dist/utils/ast-path-operations.js +419 -0
  89. package/dist/utils/ast-path-operations.js.map +1 -0
  90. package/dist/utils/config.d.ts +3 -0
  91. package/dist/utils/config.d.ts.map +1 -0
  92. package/dist/utils/config.js +49 -0
  93. package/dist/utils/config.js.map +1 -0
  94. package/dist/utils/github-setup.d.ts +74 -0
  95. package/dist/utils/github-setup.d.ts.map +1 -0
  96. package/dist/utils/github-setup.js +418 -0
  97. package/dist/utils/github-setup.js.map +1 -0
  98. package/dist/utils/idempotency.d.ts +47 -0
  99. package/dist/utils/idempotency.d.ts.map +1 -0
  100. package/dist/utils/idempotency.js +176 -0
  101. package/dist/utils/idempotency.js.map +1 -0
  102. package/dist/utils/preflight.d.ts +55 -0
  103. package/dist/utils/preflight.d.ts.map +1 -0
  104. package/dist/utils/preflight.js +261 -0
  105. package/dist/utils/preflight.js.map +1 -0
  106. package/dist/utils/versioning.d.ts +41 -0
  107. package/dist/utils/versioning.d.ts.map +1 -0
  108. package/dist/utils/versioning.js +219 -0
  109. package/dist/utils/versioning.js.map +1 -0
  110. package/docs/USER_JOURNEY_ERRORS.md +352 -0
  111. package/eslint.config.js +77 -0
  112. package/examples/basic-config.json +41 -0
  113. package/examples/monorepo-config.json +49 -0
  114. package/examples/usage.md +289 -0
  115. package/package.json +58 -0
  116. package/scripts/debug-workflows.sh +339 -0
  117. package/scripts/parse-pipeline.js +29 -0
  118. package/scripts/test-job-order.cjs +140 -0
  119. package/scripts/validate-pipeline.cjs +379 -0
  120. package/scripts/verify-job-order.sh +30 -0
  121. package/src/cli/index.ts +414 -0
  122. package/src/generators/init.tpl.ts +126 -0
  123. package/src/generators/workflows.tpl.ts +80 -0
  124. package/src/templates/actions/calculate-version.yml.tpl.ts +124 -0
  125. package/src/templates/actions/create-pr.yml.tpl.ts +147 -0
  126. package/src/templates/actions/create-tag.yml.tpl.ts +112 -0
  127. package/src/templates/actions/detect-changes.yml.tpl.ts +87 -0
  128. package/src/templates/actions/manage-branch.yml.tpl.ts +132 -0
  129. package/src/templates/actions/promote-branch.yml.tpl.ts +364 -0
  130. package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +706 -0
  131. package/src/types/index.ts +64 -0
  132. package/src/utils/README-ast-path-operations.md +390 -0
  133. package/src/utils/ast-path-operations.ts +581 -0
  134. package/src/utils/config.ts +64 -0
  135. package/src/utils/github-setup.ts +558 -0
  136. package/src/utils/idempotency.ts +215 -0
  137. package/src/utils/preflight.ts +306 -0
  138. package/src/utils/versioning.ts +244 -0
  139. package/tests/README.md +229 -0
  140. package/tests/TEST_STRUCTURE.md +256 -0
  141. package/tests/act/run-act-tests.sh +345 -0
  142. package/tests/debugging/debug-utils.ts +538 -0
  143. package/tests/debugging/debug-workflow.test.ts +339 -0
  144. package/tests/debugging/debug-workflows.sh +339 -0
  145. package/tests/debugging/iterative-debug.ts +652 -0
  146. package/tests/debugging/run-debug-tests.sh +431 -0
  147. package/tests/fixtures/basic-config.json +51 -0
  148. package/tests/fixtures/invalid-config.json +9 -0
  149. package/tests/fixtures/pipeline-generated.yml +235 -0
  150. package/tests/fixtures/pipeline-preserve-comments.yml +245 -0
  151. package/tests/fixtures/pipeline-user-modified.yml +245 -0
  152. package/tests/fixtures/test-config.json +58 -0
  153. package/tests/github-live/README.md +250 -0
  154. package/tests/github-local/JOB_WORKFLOW_TESTS.md +296 -0
  155. package/tests/github-local/README.md +240 -0
  156. package/tests/github-local/run-all-tests.sh +422 -0
  157. package/tests/github-local/test-job-workflows.sh +631 -0
  158. package/tests/github-local/test-pipeline-workflow.sh +440 -0
  159. package/tests/integration/generators.test.ts +578 -0
  160. package/tests/integration/path-based-template.test.ts +510 -0
  161. package/tests/integration/simple-path-based.test.ts +415 -0
  162. package/tests/setup.ts +56 -0
  163. package/tests/unit/ast-path-operations-extended.test.ts +302 -0
  164. package/tests/unit/cli.test.ts +541 -0
  165. package/tests/unit/config-extended.test.ts +412 -0
  166. package/tests/unit/config.test.ts +152 -0
  167. package/tests/unit/github-setup.test.ts +189 -0
  168. package/tests/unit/idempotency-isolated.test.ts +297 -0
  169. package/tests/unit/job-order.test.ts +157 -0
  170. package/tests/unit/pipeline-path-based.test.ts +511 -0
  171. package/tests/unit/validate-pipeline.test.ts +384 -0
  172. package/tests/unit/versioning-extended.test.ts +279 -0
  173. package/tests/unit/versioning.test.ts +241 -0
  174. package/tsconfig.debug.json +17 -0
  175. package/tsconfig.json +28 -0
  176. package/vitest.config.ts +51 -0
@@ -0,0 +1,50 @@
1
+ name: "Docs:Deploy"
2
+
3
+
4
+ on:
5
+ workflow_dispatch:
6
+ workflow_call:
7
+
8
+ jobs:
9
+ build:
10
+ name: Build Docusaurus
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Setup node
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 20
21
+ cache-dependency-path: 'pnpm-lock.yaml'
22
+
23
+ - name: Install pnpm
24
+ run: npm install -g pnpm
25
+
26
+ - name: Get pnpm store directory
27
+ shell: bash
28
+ run: |
29
+ echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
30
+
31
+ - uses: actions/cache@v4
32
+ name: Setup pnpm cache
33
+ with:
34
+ path: ${{ env.STORE_PATH }}
35
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }}
36
+ restore-keys: |
37
+ ${{ runner.os }}-pnpm-store-
38
+
39
+ - name: Install dependencies
40
+ run: pnpm install --frozen-lockfile --filter @madi/docs
41
+
42
+ - name: Build website
43
+ working-directory: ./apps/docs
44
+ run: pnpm run build
45
+
46
+ - name: Upload Build Artifact
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: docs-build
50
+ path: ./apps/docs/build
@@ -0,0 +1,96 @@
1
+ name: Build and Deploy to Google Cloud Storage
2
+ on:
3
+ workflow_call:
4
+ inputs:
5
+ project_id:
6
+ description: 'The project ID for the environment'
7
+ required: true
8
+ type: string
9
+ bucket:
10
+ description: 'The bucket to store the deployment'
11
+ required: true
12
+ type: string
13
+
14
+ jobs:
15
+ build_and_push_image:
16
+ environment: ${{ github.ref_name == 'main' && 'production' || github.ref_name }}
17
+ permissions:
18
+ contents: 'read'
19
+ id-token: 'write'
20
+ runs-on: ubuntu-latest
21
+ env:
22
+ WORKING_DIR: ./apps/interfaces/web
23
+ WEB_STORAGE: ${{ inputs.bucket }}
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v4
27
+
28
+ - name: Authenticate with Google
29
+ uses: 'google-github-actions/auth@v2'
30
+ with:
31
+ project_id: ${{ inputs.project_id }}
32
+ credentials_json: ${{ secrets.GCP_CREDENTIALS }}
33
+
34
+ - name: Setup node
35
+ uses: actions/setup-node@v4
36
+ with:
37
+ node-version: 20
38
+
39
+ - name: Install pnpm
40
+ run: npm install -g pnpm
41
+ working-directory: ${{ env.WORKING_DIR }}
42
+
43
+ - name: Cache pnpm store
44
+ uses: actions/cache@v4
45
+ with:
46
+ path: ~/.pnpm-store
47
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('${{ env.WORKING_DIR }}/pnpm-lock.yaml') }}
48
+ restore-keys: |
49
+ ${{ runner.os }}-pnpm-store-${{ env.WORKING_DIR }}-
50
+
51
+ - name: Install dependencies
52
+ run: pnpm install --frozen-lockfile -F @madi/web
53
+
54
+ - name: Cache Next.js
55
+ uses: actions/cache@v4
56
+ with:
57
+ path: |
58
+ ~/.pnpm-store
59
+ ${{ github.workspace }}/${{ env.WORKING_DIR }}/.next/cache
60
+ key: ${{ runner.os }}-nextjs-${{ env.WORKING_DIR }}-${{ hashFiles('${{ env.WORKING_DIR }}/pnpm-lock.yaml') }}-${{ hashFiles('${{ env.WORKING_DIR }}/**/*.js', '${{ env.WORKING_DIR }}/**/*.jsx', '${{ env.WORKING_DIR }}/**/*.ts', '${{ env.WORKING_DIR }}/**/*.tsx') }}
61
+ restore-keys: |
62
+ ${{ runner.os }}-nextjs-${{ env.WORKING_DIR }}-${{ hashFiles('${{ env.WORKING_DIR }}/pnpm-lock.yaml') }}-
63
+
64
+ - name: Build the distribution
65
+ run: pnpm -F @madi/web run build;
66
+
67
+ - name: Store release SHA in JSON file
68
+ working-directory: ${{ env.WORKING_DIR }}
69
+ run: |
70
+ mkdir -p ${{ env.WORKING_DIR }}/dist
71
+ REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
72
+ echo '{
73
+ "sha": "${{ github.sha }}",
74
+ "owner": "${{ github.repository_owner }}",
75
+ "repo": "'$REPO_NAME'",
76
+ "branch": "${{ github.ref_name }}"
77
+ }' > ${{ env.WORKING_DIR }}/dist/sha.json
78
+
79
+ - name: Download Built Documentation
80
+ uses: actions/download-artifact@v4
81
+ with:
82
+ name: docs-build
83
+ path: ${{ env.WORKING_DIR }}/dist/docs
84
+
85
+ - name: 'Set up Cloud SDK'
86
+ uses: 'google-github-actions/setup-gcloud@v2'
87
+ with:
88
+ version: 'latest'
89
+ project_id: ${{ inputs.project_id }}
90
+
91
+ - name: 'Sync dist to bucket (delete the old files)'
92
+ run: |
93
+ gsutil -m -h "Cache-Control:public, max-age=0" rsync -d -r "${{ env.WORKING_DIR }}/dist" "gs://${{ env.WEB_STORAGE }}"
94
+
95
+ ## TODO: Set max-age back up to 3600 when stack stabilizes.
96
+ # gs://web-app-hq-madi-dev-4ebd7d92-7d0cb30c/
@@ -0,0 +1,49 @@
1
+ name: "Web: Lint & Test"
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ smoke-tests:
9
+ timeout-minutes: 60
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Setup node
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 20
19
+
20
+ - name: Install pnpm
21
+ run: npm install -g pnpm
22
+
23
+ - name: Cache dependencies
24
+ uses: actions/cache@v4
25
+ with:
26
+ path: ~/.pnpm-store
27
+ key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
28
+ restore-keys: |
29
+ ${{ runner.os }}-pnpm-
30
+
31
+ - name: Install dependencies
32
+ run: pnpm install -F @madi/web
33
+
34
+ - name: Cache Playwright browsers
35
+ id: cache-playwright-browsers
36
+ uses: actions/cache@v4
37
+ with:
38
+ path: ~/.cache/ms-playwright
39
+ key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
40
+ restore-keys: |
41
+ ${{ runner.os }}-playwright-
42
+
43
+ - name: Install Playwright Browsers
44
+ run: pnpm exec playwright install --with-deps
45
+ working-directory: apps/interfaces/web
46
+
47
+ - name: Run Playwright tests
48
+ run: pnpm exec playwright test
49
+ working-directory: apps/interfaces/web
@@ -0,0 +1,82 @@
1
+ name: "Changes"
2
+
3
+ on:
4
+ workflow_call:
5
+ outputs:
6
+ api:
7
+ value: ${{ jobs.changes.outputs.api }}
8
+ web:
9
+ value: ${{ jobs.changes.outputs.web }}
10
+ docs:
11
+ value: ${{ jobs.changes.outputs.docs }}
12
+ libs:
13
+ value: ${{ jobs.changes.outputs.libs }}
14
+ cicd:
15
+ value: ${{ jobs.changes.outputs.cicd }}
16
+
17
+ workflow_dispatch:
18
+
19
+ jobs:
20
+ changes:
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ outputs:
26
+ api: ${{ steps.merge.outputs.api }}
27
+ web: ${{ steps.merge.outputs.web }}
28
+ docs: ${{ steps.merge.outputs.docs }}
29
+ libs: ${{ steps.merge.outputs.libs }}
30
+ cicd: ${{ steps.merge.outputs.cicd }}
31
+ steps:
32
+
33
+ - uses: actions/checkout@v4
34
+ with:
35
+ fetch-depth: 0
36
+
37
+ - name: Set Base Branch
38
+ id: set-base
39
+ ## if base branch is develop compare to test. Test and Main always fully deploy
40
+ run: |
41
+ base_branch=$(
42
+ if [[ '${{ github.ref }}' == 'refs/heads/develop' ]]; then
43
+ echo 'test'
44
+ else
45
+ echo 'develop'
46
+ fi
47
+ )
48
+ echo "Base branch determined: $base_branch"
49
+ echo "base_branch=$base_branch" >> $GITHUB_ENV
50
+
51
+ - uses: dorny/paths-filter@v3
52
+ id: filter
53
+ with:
54
+ base: ${{ env.base_branch }}
55
+ filters: |
56
+ api:
57
+ - 'apps/api/**'
58
+ web:
59
+ - 'apps/interfaces/web/**'
60
+ docs:
61
+ - 'apps/docs/**'
62
+ libs:
63
+ - 'libs/**'
64
+ cicd:
65
+ - '.github/workflows/**'
66
+
67
+ - name: Merge filter outputs with branch condition
68
+ id: merge
69
+ run: |
70
+ echo "api=${{ steps.filter.outputs.api == 'true' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' }}" >> $GITHUB_OUTPUT
71
+ echo "web=${{ steps.filter.outputs.web == 'true' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' }}" >> $GITHUB_OUTPUT
72
+ echo "docs=${{ steps.filter.outputs.docs == 'true' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' }}" >> $GITHUB_OUTPUT
73
+ echo "libs=${{ steps.filter.outputs.libs == 'true' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' }}" >> $GITHUB_OUTPUT
74
+ echo "cicd=${{ steps.filter.outputs.cicd == 'true' || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/test' }}" >> $GITHUB_OUTPUT
75
+
76
+ - name: Debug Paths Filter Outputs
77
+ run: |
78
+ echo "API: ${{ steps.merge.outputs.api }}"
79
+ echo "WEB: ${{ steps.merge.outputs.web }}"
80
+ echo "DOCS: ${{ steps.merge.outputs.docs }}"
81
+ echo "LIBS: ${{ steps.merge.outputs.libs }}"
82
+ echo "CICD: ${{ steps.merge.outputs.cicd }}"
@@ -0,0 +1,96 @@
1
+ name: "Create PR"
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ version:
7
+ description: 'The new version to deploy'
8
+ required: true
9
+ type: string
10
+ workflow_dispatch:
11
+
12
+ jobs:
13
+ create-pr:
14
+ runs-on: ubuntu-latest
15
+ if: ${{ github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/test' }}
16
+ steps:
17
+ - name: Checkout Code
18
+ uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0 # Ensures full history for version tracking
21
+
22
+ - name: Set Up Git
23
+ run: |
24
+ git config user.name "github-actions[bot]"
25
+ git config user.email "github-actions[bot]@users.noreply.github.com"
26
+
27
+ - name: Determine Base and Target Version
28
+ id: versioning
29
+ run: |
30
+ set -x
31
+ BASE_BRANCH=${{ github.ref_name == 'develop' && 'test' || 'main' }}
32
+
33
+ # Fetch latest tag on base branch
34
+ # Get the current commit hash on the base branch (test or main)
35
+ BASE_COMMIT_HASH=$(git rev-parse origin/$BASE_BRANCH)
36
+
37
+ # Get the tags that are on or before the base commit
38
+ PREV_VERSION=$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | while read tag; do git merge-base --is-ancestor "$tag" "$BASE_COMMIT_HASH" && echo "$tag" && break; done)
39
+
40
+ if [[ -z "$PREV_VERSION" ]]; then
41
+ echo "No previous version found, aborting."
42
+ exit 1
43
+ fi
44
+
45
+ echo "Previous version: $PREV_VERSION"
46
+ echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
47
+ echo "PREV_VERSION=$PREV_VERSION" >> $GITHUB_ENV
48
+
49
+ - name: Create Fake Branches
50
+ run: |
51
+ NEW_BRANCH="temp-${BASE_BRANCH}-${{ inputs.version }}"
52
+ OLD_BRANCH="temp-${BASE_BRANCH}-${PREV_VERSION}"
53
+
54
+ # Fetch the latest changes
55
+ git fetch origin
56
+
57
+ # Create a new fake branch from the current version of develop (or base branch)
58
+ git checkout -b $NEW_BRANCH origin/${{ github.ref_name }}
59
+ git push origin $NEW_BRANCH --force
60
+
61
+ # Create an old branch based on the previous version on the base branch (test or main)
62
+ git checkout -b $OLD_BRANCH origin/$BASE_BRANCH
63
+ git push origin $OLD_BRANCH --force
64
+
65
+ echo "NEW_BRANCH=$NEW_BRANCH" >> $GITHUB_ENV
66
+ echo "OLD_BRANCH=$OLD_BRANCH" >> $GITHUB_ENV
67
+
68
+ - name: Create Pull Request
69
+ uses: actions/github-script@v6
70
+ with:
71
+ script: |
72
+ const base = process.env.OLD_BRANCH;
73
+ const head = process.env.NEW_BRANCH;
74
+ const version = '${{ inputs.version }}';
75
+
76
+ const { data: existingPRs } = await github.rest.pulls.list({
77
+ owner: context.repo.owner,
78
+ repo: context.repo.repo,
79
+ head: head,
80
+ base: base,
81
+ state: 'open'
82
+ });
83
+
84
+ if (existingPRs.length > 0) {
85
+ console.log('A pull request already exists.');
86
+ } else {
87
+ const { data: pullRequest } = await github.rest.pulls.create({
88
+ owner: context.repo.owner,
89
+ repo: context.repo.repo,
90
+ title: `ci: Promote ${process.env.BASE_BRANCH} from ${process.env.PREV_VERSION} to ${version}`,
91
+ head: head,
92
+ base: base,
93
+ body: 'This PR is automatically created by CI.'
94
+ });
95
+ console.log(`Created pull request: ${pullRequest.html_url}`);
96
+ }
@@ -0,0 +1,43 @@
1
+ name: "Environment Check"
2
+
3
+ on:
4
+ workflow_call:
5
+ outputs:
6
+ project_id:
7
+ description: "The determined project id"
8
+ value: ${{ jobs.check.outputs.project_id }}
9
+ bucket:
10
+ description: "The determined bucket"
11
+ value: ${{ jobs.check.outputs.bucket }}
12
+
13
+ jobs:
14
+ check:
15
+ runs-on: ubuntu-latest
16
+ if: ${{ github.ref_name == 'main' || github.ref_name == 'develop' || github.ref_name == 'test' }}
17
+ outputs:
18
+ project_id: ${{ steps.set-vars.outputs.project_id }}
19
+ bucket: ${{ steps.set-vars.outputs.bucket }}
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Set environment variables
25
+ id: set-vars
26
+ run: |
27
+ echo "Current branch: ${{ github.ref_name }}"
28
+ if [ "${{ github.ref_name }}" = "main" ]; then
29
+ echo "Using PROD project ID"
30
+ echo "project_id=${{ vars.PROJECT_ID_PROD }}" >> $GITHUB_OUTPUT
31
+ echo "bucket=${{ vars.WEB_STORAGE_PROD }}" >> $GITHUB_OUTPUT
32
+ elif [ "${{ github.ref_name }}" = "develop" ]; then
33
+ echo "Using DEVELOP project ID"
34
+ echo "project_id=${{ vars.PROJECT_ID_DEVELOP }}" >> $GITHUB_OUTPUT
35
+ echo "bucket=${{ vars.WEB_STORAGE_DEVELOP }}" >> $GITHUB_OUTPUT
36
+ elif [ "${{ github.ref_name }}" = "test" ]; then
37
+ echo "Using TEST project ID"
38
+ echo "project_id=${{ vars.PROJECT_ID_TEST }}" >> $GITHUB_OUTPUT
39
+ echo "bucket=${{ vars.WEB_STORAGE_TEST }}" >> $GITHUB_OUTPUT
40
+ else
41
+ echo "Error: Unsupported branch ${{ github.ref_name }}"
42
+ exit 1
43
+ fi
@@ -0,0 +1,103 @@
1
+ name: "Fast Forward After PR Merge"
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - closed # Only run when PR is merged
7
+
8
+ env:
9
+ pipefile: 'pipe.yml'
10
+
11
+ jobs:
12
+ fast-forward:
13
+ if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'temp-test') || startsWith(github.event.pull_request.head.ref, 'temp-main')
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Verify PR Source is a Fake Branch
17
+ id: verify-branch
18
+ run: |
19
+ PR_HEAD="${{ github.event.pull_request.head.ref }}"
20
+ PR_BASE="${{ github.event.pull_request.base.ref }}"
21
+
22
+
23
+ # Check if the PR source branch matches the fake branch pattern
24
+ if [[ ! "$PR_HEAD" =~ ^temp-(test|main)-v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
25
+ echo "Skipping: PR did not come from an auto-generated fake branch."
26
+ exit 1
27
+ fi
28
+
29
+ # Extract version and base branch from the PR branch name
30
+ BASE_BRANCH=$(echo "$PR_BASE" | cut -d'-' -f2)
31
+ OLD_VERSION=$(echo "$PR_BASE" | cut -d'-' -f3-)
32
+ NEXT_VERSION=$(echo "$PR_HEAD" | cut -d'-' -f3-)
33
+
34
+ echo "BASE_BRANCH=$BASE_BRANCH"
35
+ echo "OLD_VERSION=$OLD_VERSION"
36
+ echo "NEXT_VERSION=$NEXT_VERSION"
37
+
38
+ # Set as environment variables for later steps
39
+ echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
40
+ echo "OLD_VERSION=$OLD_VERSION" >> $GITHUB_ENV
41
+ echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV
42
+
43
+ - name: Checkout Repository
44
+ uses: actions/checkout@v4
45
+ with:
46
+ fetch-depth: 0 # Ensure full history for fast-forwarding
47
+
48
+ - name: Set Up Git
49
+ run: |
50
+ git config user.name "github-actions[bot]"
51
+ git config user.email "github-actions[bot]@users.noreply.github.com"
52
+
53
+ - name: Get Latest Commit from Head Branch
54
+ id: get-commit
55
+ run: |
56
+ PR_HEAD="${{ github.event.pull_request.head.ref }}"
57
+ PR_BASE="${{ github.event.pull_request.base.ref }}"
58
+
59
+ # Ensure the head branch is checked out
60
+ git fetch origin $PR_HEAD:$PR_HEAD
61
+ git checkout $PR_HEAD
62
+
63
+ git rev-parse $PR_HEAD
64
+
65
+ # Fetch the latest commit hash from the head branch
66
+ COMMIT_HASH=$(git rev-parse $PR_HEAD)
67
+
68
+ if [[ -z "$COMMIT_HASH" ]]; then
69
+ echo "Failed to find commit for branch $PR_HEAD"
70
+ exit 1
71
+ fi
72
+
73
+ echo "Found commit: $COMMIT_HASH"
74
+ echo "COMMIT_HASH=$COMMIT_HASH" >> $GITHUB_ENV
75
+
76
+ - name: Fast Forward Target Branch
77
+ run: |
78
+ git fetch origin
79
+
80
+ # Checkout the target branch (test or main)
81
+ git checkout $BASE_BRANCH
82
+
83
+ # Ensure fast-forward merge
84
+ git merge --ff-only $COMMIT_HASH
85
+
86
+ # Push the changes back to the target branch
87
+ git push origin $BASE_BRANCH
88
+
89
+ - name: Delete Temporary Branches
90
+ run: |
91
+ # Delete the fake branches after the merge
92
+ git push origin --delete "temp-${BASE_BRANCH}-${OLD_VERSION}"
93
+ git push origin --delete "temp-${BASE_BRANCH}-${NEXT_VERSION}"
94
+
95
+ echo "Temporary branches deleted"
96
+
97
+ - name: Trigger Test and Deploy Workflow
98
+ run: |
99
+ curl -X POST \
100
+ -H "Accept: application/vnd.github.v3+json" \
101
+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
102
+ https://api.github.com/repos/${{ github.repository }}/actions/workflows/${{env.pipefile}}/dispatches \
103
+ -d "{\"ref\":\"${BASE_BRANCH}\", \"inputs\": {\"migration_input\": \"false\", \"seed_input\": \"false\"}}"
@@ -0,0 +1,64 @@
1
+ name: "Web: Lint & Test"
2
+
3
+ on:
4
+ workflow_call:
5
+ workflow_dispatch:
6
+
7
+ jobs:
8
+ lint:
9
+ name: ESLint
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repo
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Setup node
16
+ uses: actions/setup-node@v4
17
+ with:
18
+ node-version: 20
19
+
20
+ - name: Install pnpm
21
+ run: npm install -g pnpm
22
+
23
+ - name: Cache dependencies
24
+ uses: actions/cache@v4
25
+ with:
26
+ path: ~/.pnpm-store
27
+ key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
28
+ restore-keys: |
29
+ ${{ runner.os }}-pnpm-
30
+
31
+ - name: Install dependencies
32
+ run: pnpm install --frozen-lockfile
33
+
34
+ - name: Lint
35
+ run: pnpm run lint:strict
36
+
37
+ prettier:
38
+ name: Prettier
39
+ runs-on: ubuntu-latest
40
+ steps:
41
+ - name: Checkout repo
42
+ uses: actions/checkout@v4
43
+
44
+ - name: Setup node
45
+ uses: actions/setup-node@v4
46
+ with:
47
+ node-version: 20
48
+
49
+ - name: Install pnpm
50
+ run: npm install -g pnpm
51
+
52
+ - name: Cache dependencies
53
+ uses: actions/cache@v4
54
+ with:
55
+ path: ~/.pnpm-store
56
+ key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
57
+ restore-keys: |
58
+ ${{ runner.os }}-pnpm-
59
+
60
+ - name: Install dependencies
61
+ run: pnpm install --frozen-lockfile
62
+
63
+ - name: Prettier check
64
+ run: npm run format:check
@@ -0,0 +1,70 @@
1
+ name: "PR Title Format Check"
2
+
3
+ on:
4
+ pull_request_target:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - synchronize
9
+ - reopened
10
+ pull_request:
11
+ types:
12
+ - opened
13
+ - edited
14
+ - synchronize
15
+ - reopened
16
+
17
+ permissions:
18
+ pull-requests: read
19
+
20
+ jobs:
21
+ main:
22
+ name: Validate PR title
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: amannn/action-semantic-pull-request@v5
26
+ id: lint_pr_title
27
+ env:
28
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29
+ with:
30
+ # Configure which types are allowed (newline-delimited).
31
+ # Default: https://github.com/commitizen/conventional-commit-types
32
+ types: |
33
+ fix
34
+ feat
35
+ docs
36
+ style
37
+ chore
38
+ refactor
39
+ perf
40
+ test
41
+ ci
42
+ build
43
+ revert
44
+ major
45
+ requireScope: false
46
+
47
+
48
+ - uses: marocchino/sticky-pull-request-comment@v2
49
+ # When the previous steps fails, the workflow would stop. By adding this
50
+ # condition you can continue the execution with the populated error message.
51
+ if: always() && (steps.lint_pr_title.outputs.error_message != null)
52
+ with:
53
+ header: pr-title-lint-error
54
+ message: |
55
+ Hey there and thank you for opening this pull request! 👋🏼
56
+
57
+ We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
58
+
59
+ Details:
60
+
61
+ ```
62
+ ${{ steps.lint_pr_title.outputs.error_message }}
63
+ ```
64
+
65
+ # Delete a previous comment when the issue has been resolved
66
+ - if: ${{ steps.lint_pr_title.outputs.error_message == null }}
67
+ uses: marocchino/sticky-pull-request-comment@v2
68
+ with:
69
+ header: pr-title-lint-error
70
+ delete: true
@@ -0,0 +1,27 @@
1
+ name: Enforce PR Title as Commit Message
2
+
3
+ on:
4
+ pull_request:
5
+ types: [closed]
6
+
7
+ jobs:
8
+ enforce-squash-message:
9
+ if: github.event.pull_request.merged == true && github.event.pull_request.merge_commit_sha != null
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v4
14
+
15
+ - name: Check squash commit message
16
+ run: |
17
+ TITLE="${{ github.event.pull_request.title }}"
18
+ SHA="${{ github.event.pull_request.merge_commit_sha }}"
19
+ MESSAGE=$(git log -1 --pretty=%B $SHA)
20
+
21
+ echo "PR Title: $TITLE"
22
+ echo "Squash Commit Message: $MESSAGE"
23
+
24
+ if [[ "$MESSAGE" != "$TITLE" ]]; then
25
+ echo "❌ Commit message does not match PR title!"
26
+ exit 1
27
+ fi