From ae13db9d6ba049d4582af8352e0559a2d709d473 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Mon, 21 Sep 2026 18:50:41 -0300 Subject: [PATCH 1/2] feat: publish workflow lock provenance --- docs/workflow-adoption-model.md | 20 +++++++++++++++++++ .../sync-workflow-templates.yml.patch | 9 ++++++--- tests/test_portable_workflow_sync_auth.py | 18 +++++++++++++++++ .../sync-workflow-templates.yml | 11 +++++++++- 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/docs/workflow-adoption-model.md b/docs/workflow-adoption-model.md index 38ce0ff..91888f6 100644 --- a/docs/workflow-adoption-model.md +++ b/docs/workflow-adoption-model.md @@ -109,3 +109,23 @@ Before accepting a new shared workflow: - Are permissions least-privilege? - Are third-party actions pinned according to project policy? - Does the consumer have a documented update and divergence path? + +## Consumer lock provenance + +Materialized workflow consumers use `.github/actions-lock.txt` as a management +and provenance record. + +New lock entries use SHA-256 and record: + +- the installed workflow filename; +- the catalog workflow digest; +- the released `github-workflows` platform version; +- the immutable `github-workflows` source commit used by the updater; +- the exact `LibreCodeCoop/.github` catalog commit checked out by the run. + +Legacy two-column MD5 locks remain readable. The next successful synchronization +migrates them deterministically to the provenance format without rewriting a +workflow when its effective bytes are unchanged. + +The consumer-local `.patch` remains authoritative for deliberate +local differences, and unexplained divergence continues to fail closed. diff --git a/patches/nextcloud/sync-workflow-templates.yml.patch b/patches/nextcloud/sync-workflow-templates.yml.patch index 59a4472..b9b2ed2 100644 --- a/patches/nextcloud/sync-workflow-templates.yml.patch +++ b/patches/nextcloud/sync-workflow-templates.yml.patch @@ -33,7 +33,7 @@ name: Update workflows in ${{ matrix.branches }} -@@ -42,12 +45,105 @@ +@@ -42,12 +45,111 @@ with: require: admin @@ -140,7 +140,7 @@ - name: Checkout app uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 -@@ -56,86 +152,30 @@ +@@ -56,86 +158,33 @@ path: target ref: ${{ matrix.branches }} @@ -209,10 +209,13 @@ - echo "DRAFT_ONLY=${draft_only}" >> $GITHUB_ENV + - name: Synchronize workflow templates + id: sync -+ uses: LibreCodeCoop/github-workflows/actions/sync-workflows@42333e05774f13b83283314079d03614a8beaf82 # v0.1.0 ++ uses: LibreCodeCoop/github-workflows/actions/sync-workflows@002f17274ba1eade3351ba81890bf53674b37c43 # v0.4.0 + with: + source: source/workflow-templates + target: target ++ platform-version: v0.4.0 ++ source-commit: 002f17274ba1eade3351ba81890bf53674b37c43 ++ catalog-commit: ${{ steps.catalog-revision.outputs.sha }} - name: Create Pull Request + if: ${{ steps.sync.outputs.changed == 'true' }} diff --git a/tests/test_portable_workflow_sync_auth.py b/tests/test_portable_workflow_sync_auth.py index e6a24c4..bac0ac7 100644 --- a/tests/test_portable_workflow_sync_auth.py +++ b/tests/test_portable_workflow_sync_auth.py @@ -42,6 +42,24 @@ def test_github_token_limitation_is_visible_in_template(self) -> None: content, ) + def test_sync_action_is_pinned_with_release_and_catalog_provenance(self) -> None: + content = TEMPLATE.read_text(encoding="utf-8") + + self.assertIn( + "actions/sync-workflows@002f17274ba1eade3351ba81890bf53674b37c43 # v0.4.0", + content, + ) + self.assertIn("platform-version: v0.4.0", content) + self.assertIn( + "source-commit: 002f17274ba1eade3351ba81890bf53674b37c43", + content, + ) + self.assertIn("id: catalog-revision", content) + self.assertIn( + "catalog-commit: ${{ steps.catalog-revision.outputs.sha }}", + content, + ) + if __name__ == "__main__": unittest.main() diff --git a/workflow-templates/sync-workflow-templates.yml b/workflow-templates/sync-workflow-templates.yml index 69f1612..e41ce4e 100644 --- a/workflow-templates/sync-workflow-templates.yml +++ b/workflow-templates/sync-workflow-templates.yml @@ -145,6 +145,12 @@ jobs: path: source repository: LibreCodeCoop/.github + - name: Record workflow catalog revision + id: catalog-revision + working-directory: source + shell: bash + run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + - name: Checkout app uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -154,10 +160,13 @@ jobs: - name: Synchronize workflow templates id: sync - uses: LibreCodeCoop/github-workflows/actions/sync-workflows@42333e05774f13b83283314079d03614a8beaf82 # v0.1.0 + uses: LibreCodeCoop/github-workflows/actions/sync-workflows@002f17274ba1eade3351ba81890bf53674b37c43 # v0.4.0 with: source: source/workflow-templates target: target + platform-version: v0.4.0 + source-commit: 002f17274ba1eade3351ba81890bf53674b37c43 + catalog-commit: ${{ steps.catalog-revision.outputs.sha }} - name: Create Pull Request if: ${{ steps.sync.outputs.changed == 'true' }} From 351fe1f93c4ed175584031f7c51235446437afe6 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Mon, 21 Sep 2026 18:51:41 -0300 Subject: [PATCH 2/2] fix: include catalog revision in generated patch --- patches/nextcloud/sync-workflow-templates.yml.patch | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/patches/nextcloud/sync-workflow-templates.yml.patch b/patches/nextcloud/sync-workflow-templates.yml.patch index b9b2ed2..2714f63 100644 --- a/patches/nextcloud/sync-workflow-templates.yml.patch +++ b/patches/nextcloud/sync-workflow-templates.yml.patch @@ -137,6 +137,12 @@ path: source - repository: nextcloud/.github + repository: LibreCodeCoop/.github ++ ++ - name: Record workflow catalog revision ++ id: catalog-revision ++ working-directory: source ++ shell: bash ++ run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" - name: Checkout app uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1