diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..3551bab2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,40 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 + labels: + - dependencies + - github-actions + commit-message: + prefix: deps + include: scope + groups: + actions-minor-and-patch: + applies-to: version-updates + update-types: + - minor + - patch + + - package-ecosystem: gomod + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 10 + labels: + - dependencies + - go + commit-message: + prefix: deps + include: scope + groups: + gomod-minor-and-patch: + applies-to: version-updates + update-types: + - minor + - patch diff --git a/.github/workflows/branch-preview.yaml b/.github/workflows/branch-preview.yaml index 2409d579..92ba2e80 100644 --- a/.github/workflows/branch-preview.yaml +++ b/.github/workflows/branch-preview.yaml @@ -17,7 +17,7 @@ jobs: outputs: version: ${{ steps.version.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get next version uses: reecetech/version-increment@2023.10.2 id: base-version @@ -40,16 +40,16 @@ jobs: cicd-bot-telegram-token: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-token }} cicd-bot-telegram-chat-id: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-chat-id }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: fregante/setup-git-user@v2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: go-version: '1.25' - - name: install sc tool (latest release) - shell: bash - run: |- - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main + - name: install welder tool + uses: simple-container-com/actions/install-welder@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -70,7 +70,7 @@ jobs: SKIP_EMBEDDINGS: "true" run: |- git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git - bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run rebuild + welder run rebuild - name: clean run: | mkdir -p dist @@ -124,7 +124,7 @@ jobs: - os: darwin arch: amd64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -166,7 +166,7 @@ jobs: cmd: cloud-helpers output: dist/cloud-helpers steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -192,7 +192,7 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: [prepare, build-setup] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -217,7 +217,7 @@ jobs: dockerfile: cloud-helpers.aws.Dockerfile tag_prefix: "simplecontainer/cloud-helpers:aws-" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: download ${{ matrix.target }} binary uses: actions/download-artifact@v4 with: @@ -225,10 +225,8 @@ jobs: path: dist - name: fix binary permissions run: chmod +x dist/${{ matrix.binary }} - - name: install sc tool (latest release) - shell: bash - run: |- - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -267,7 +265,7 @@ jobs: # Runs in parallel with publish-git-tag. needs: [prepare, build-setup, build-platforms, test] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: download all sc platform artifacts uses: actions/download-artifact@v4 with: @@ -280,10 +278,8 @@ jobs: path: bin - name: fix bin tools permissions run: chmod +x bin/* - - name: install sc tool (latest release) - shell: bash - run: |- - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -319,7 +315,7 @@ jobs: # Does not need build-platforms or publish-sc-preview. Runs in parallel with publish-sc-preview. needs: [prepare, docker-build] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - uses: fregante/setup-git-user@v2 @@ -364,18 +360,17 @@ jobs: - publish-git-tag - docker-build steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: ${{ always() }} - name: Extract git reference id: extract_git_ref if: ${{ always() }} shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} run: |- - cat <<'EOF' > /tmp/commit_message.txt - ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} - EOF - message="$(cat /tmp/commit_message.txt | tr -d '\n')" + message="$(printf '%s' "$COMMIT_MESSAGE" | tr -d '\n')" if [ ${#message} -gt 200 ]; then truncated_message="${message:0:80}...${message: -80}" message="$truncated_message" @@ -420,29 +415,39 @@ jobs: Docker image: \`simplecontainer/github-actions:${VERSION}\` - ### Install this SC version via CLI + ### Install this SC version in your CI - \`\`\`bash - SIMPLE_CONTAINER_VERSION=${VERSION} curl -s "https://dist.simple-container.com/sc.sh" | bash + \`\`\`yaml + - uses: simple-container-com/actions/install-sc@main + with: + version: ${VERSION} \`\`\` - > Preview build from branch \`${BRANCH}\`. Running \`sc.sh\` without \`SIMPLE_CONTAINER_VERSION\` will **not** pick up this version. + > Preview build from branch \`${BRANCH}\`. The \`install-sc\` action pins the binary to the exact preview version above and verifies it on download. ENDSUMMARY - - uses: yanzay/notify-telegram@v0.1.0 + - name: Notify Telegram (success) if: ${{ success() && !contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ✅ preview published (${{ steps.extract_git_ref.outputs.branch }}) (v${{ needs.prepare.outputs.version }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} - - uses: yanzay/notify-telegram@v0.1.0 + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '✅ Preview published: ' + link-url: ${{ format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: 'v${{ needs.prepare.outputs.version }}' + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' + - name: Notify Telegram (failure) if: ${{ failure() || contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ❗ preview failed (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '❗ Preview failed: ' + link-url: ${{ format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: 'v${{ needs.prepare.outputs.version }}' + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' - name: Build failed due to previously failed steps id: fail_if_needed diff --git a/.github/workflows/branch.yaml b/.github/workflows/branch.yaml index 9220acf7..1b30b373 100644 --- a/.github/workflows/branch.yaml +++ b/.github/workflows/branch.yaml @@ -17,16 +17,16 @@ jobs: cicd-bot-telegram-token: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-token }} cicd-bot-telegram-chat-id: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-chat-id }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: fregante/setup-git-user@v2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: go-version: '1.25' - - name: install sc tool (latest release) - shell: bash - run: |- - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main + - name: install welder tool + uses: simple-container-com/actions/install-welder@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -47,7 +47,7 @@ jobs: SKIP_EMBEDDINGS: "true" run: |- git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git - bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run rebuild + welder run rebuild - name: clean run: | mkdir -p dist @@ -101,7 +101,7 @@ jobs: - os: darwin arch: amd64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -141,7 +141,7 @@ jobs: cmd: cloud-helpers output: dist/cloud-helpers steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -166,7 +166,7 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: build-setup steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -187,7 +187,7 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: build-setup steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -209,38 +209,44 @@ jobs: - build-github-actions-staging - test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: ${{ always() }} - name: Extract git reference id: extract_git_ref if: ${{ always() }} shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} run: |- - cat <<'EOF' > /tmp/commit_message.txt - ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} - EOF - message="$(cat /tmp/commit_message.txt | tr -d '\n')" + message="$(printf '%s' "$COMMIT_MESSAGE" | tr -d '\n')" echo "branch=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT echo "message=$message" >> $GITHUB_OUTPUT echo "author=$GITHUB_ACTOR" >> $GITHUB_OUTPUT echo "url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - # Notify telegram - - uses: yanzay/notify-telegram@v0.1.0 - if: ${{ success() && !contains(needs.*.result, 'failure') }} + - name: Notify Telegram (success) + if: ${{ success() && !contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ✅ success (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} - - uses: yanzay/notify-telegram@v0.1.0 + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '✅ CI passed: ' + link-url: ${{ github.event.pull_request.html_url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: "${{ github.event.pull_request.title && format('PR #{0}: {1}', github.event.pull_request.number, github.event.pull_request.title) || github.workflow }}" + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' + - name: Notify Telegram (failure) if: ${{ failure() || contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ❗ failure (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '❗ CI failed: ' + link-url: ${{ github.event.pull_request.html_url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: "${{ github.event.pull_request.title && format('PR #{0}: {1}', github.event.pull_request.number, github.event.pull_request.title) || github.workflow }}" + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' - name: Build failed due to previously failed steps id: fail_if_needed diff --git a/.github/workflows/build-staging.yml b/.github/workflows/build-staging.yml index 49c458fa..76def95a 100644 --- a/.github/workflows/build-staging.yml +++ b/.github/workflows/build-staging.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 @@ -39,23 +39,10 @@ jobs: restore-keys: | cli-tools-${{ runner.os }}- - - name: Install CLI tools - run: | - # Install SC CLI if not cached - if ! command -v sc &> /dev/null; then - echo "Installing Simple Container CLI..." - curl -s "https://dist.simple-container.com/sc.sh" | bash - else - echo "✅ SC CLI already cached and available" - fi - - # Install Welder if not cached - if ! command -v welder &> /dev/null; then - echo "Installing Welder..." - curl -Ls "https://welder.simple-container.com/welder.sh" | bash - else - echo "✅ Welder already cached and available" - fi + - name: install sc tool + uses: simple-container-com/actions/install-sc@main + - name: install welder tool + uses: simple-container-com/actions/install-welder@main - name: Prepare secrets for build run: | @@ -92,6 +79,7 @@ jobs: - name: Build and push Docker image with BuildKit caching env: DOCKER_BUILDKIT: 1 + REF_NAME: ${{ github.ref_name }} run: | # Build and push with advanced caching using BuildKit docker buildx build \ @@ -100,7 +88,7 @@ jobs: --cache-to type=gha,mode=max \ --file github-actions-staging.Dockerfile \ --tag simplecontainer/github-actions:staging \ - --tag simplecontainer/github-actions:${{ github.ref_name }} \ + --tag "simplecontainer/github-actions:$REF_NAME" \ --push \ . @@ -121,12 +109,14 @@ jobs: . - name: Image built successfully + env: + REF_NAME: ${{ github.ref_name }} run: | echo "🎉 GitHub Actions and Caddy staging images built successfully with BuildKit + GitHub Actions caching!" echo "" echo "🚀 The staging images are now available:" echo " simplecontainer/github-actions:staging" - echo " simplecontainer/github-actions:${{ github.ref_name }}" + echo " simplecontainer/github-actions:$REF_NAME" echo " simplecontainer/caddy:staging" echo " simplecontainer/caddy:$VERSION" echo "" @@ -148,40 +138,45 @@ jobs: needs: - build-staging steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: ${{ always() }} - name: Extract git reference id: extract_git_ref if: ${{ always() }} shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} run: |- - cat <<'EOF' > /tmp/commit_message.txt - ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} - EOF - message="$(cat /tmp/commit_message.txt | tr -d '\n')" + message="$(printf '%s' "$COMMIT_MESSAGE" | tr -d '\n')" echo "branch=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT echo "message=$message" >> $GITHUB_OUTPUT echo "author=$GITHUB_ACTOR" >> $GITHUB_OUTPUT echo "url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - # Notify telegram on success - - uses: yanzay/notify-telegram@v0.1.0 - if: ${{ success() && !contains(needs.*.result, 'failure') }} + - name: Notify Telegram (success) + if: ${{ success() && !contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-staging.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-staging.outputs.cicd-bot-telegram-token }} - status: ✅ staging build success (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} - - # Notify telegram on failure - - uses: yanzay/notify-telegram@v0.1.0 + chat-id: ${{ needs.build-staging.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-staging.outputs.cicd-bot-telegram-token }} + text: '🏗️ Staging built: ' + link-url: ${{ github.event.head_commit.url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: '${{ github.workflow }}' + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' + + - name: Notify Telegram (failure) if: ${{ failure() || contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-staging.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-staging.outputs.cicd-bot-telegram-token }} - status: ❗ staging build failure (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} + chat-id: ${{ needs.build-staging.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-staging.outputs.cicd-bot-telegram-token }} + text: '❗ Staging failed: ' + link-url: ${{ github.event.head_commit.url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: '${{ github.workflow }}' + suffix: ' on ${{ github.head_ref || github.ref_name }} by ${{ steps.extract_git_ref.outputs.author }}' - name: Build failed due to previously failed steps id: fail_if_needed diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 58e6b57f..30e1bf4c 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -20,7 +20,7 @@ jobs: outputs: version: ${{ steps.version.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get next version uses: reecetech/version-increment@2023.10.2 id: version @@ -37,17 +37,16 @@ jobs: cicd-bot-telegram-token: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-token }} cicd-bot-telegram-chat-id: ${{ steps.telegram-secrets.outputs.cicd-bot-telegram-chat-id }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: fregante/setup-git-user@v2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: go-version: '1.25' - - name: install sc tool (latest release) - shell: bash - run: |- - # Install latest SC release to get secrets for embeddings generation - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main + - name: install welder tool + uses: simple-container-com/actions/install-welder@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -68,7 +67,7 @@ jobs: SKIP_EMBEDDINGS: "true" run: |- git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git - bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run rebuild + welder run rebuild - name: clean run: | mkdir -p dist @@ -127,7 +126,7 @@ jobs: - os: darwin arch: amd64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -175,7 +174,7 @@ jobs: cmd: cloud-helpers output: dist/cloud-helpers steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -201,7 +200,7 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: [prepare, build-setup] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -225,7 +224,7 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: [prepare, build-setup] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Go with Blacksmith caching uses: useblacksmith/setup-go@v6 with: @@ -239,7 +238,7 @@ jobs: runs-on: ubuntu-latest needs: [prepare, build-setup] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: restore cached schemas uses: actions/cache@v4 with: @@ -286,7 +285,7 @@ jobs: simplecontainer/cloud-helpers:aws-latest simplecontainer/cloud-helpers:aws-${{ needs.prepare.outputs.version }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: download github-actions-staging binary if: matrix.image == 'github-actions-staging' uses: actions/download-artifact@v4 @@ -305,11 +304,8 @@ jobs: with: name: cloud-helpers-binary path: dist - - name: install sc tool (latest release) - shell: bash - run: |- - # Install latest SC release to get secrets for embeddings generation - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -353,13 +349,12 @@ jobs: runs-on: blacksmith-8vcpu-ubuntu-2204 needs: [prepare, build-setup, build-platforms, build-binaries, build-github-actions-staging, test, build-docs, docker-build] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: fregante/setup-git-user@v2 - - name: install sc tool (latest release) - shell: bash - run: |- - # Install latest SC release to get secrets for embeddings generation - curl -s "https://dist.simple-container.com/sc.sh" | bash + - name: install sc tool + uses: simple-container-com/actions/install-sc@main + - name: install welder tool + uses: simple-container-com/actions/install-welder@main - name: prepare secrets for build run: | cat << EOF > ./.sc/cfg.default.yaml @@ -401,13 +396,13 @@ jobs: VERSION: ${{ needs.prepare.outputs.version }} run: |- git remote set-url origin https://${{ secrets.GITHUB_TOKEN }}@github.com/simple-container-com/api.git - bash <(curl -Ls "https://welder.simple-container.com/welder.sh") run tag-release + welder run tag-release - name: publish sc tool shell: bash env: VERSION: ${{ needs.prepare.outputs.version }} run: |- - bash <(curl -Ls "https://welder.simple-container.com/welder.sh") deploy -e prod --timestamps + welder deploy -e prod --timestamps finalize: name: Finalize build and deploy for ${{ needs.prepare.outputs.stack-name }} @@ -420,46 +415,52 @@ jobs: - build-setup - docker-finalize steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 if: ${{ always() }} - name: Extract git reference id: extract_git_ref if: ${{ always() }} shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} run: |- - cat <<'EOF' > /tmp/commit_message.txt - ${{ github.event.head_commit.message || github.event.workflow_run.head_commit.message }} - EOF - message="$(cat /tmp/commit_message.txt | tr -d '\n')" - + message="$(printf '%s' "$COMMIT_MESSAGE" | tr -d '\n')" + # Truncate message if too long for Telegram (max ~200 chars to leave room for other content) if [ ${#message} -gt 200 ]; then # Take first 80 chars and last 80 chars with separator truncated_message="${message:0:80}...${message: -80}" message="$truncated_message" fi - + echo "branch=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT echo "message=$message" >> $GITHUB_OUTPUT echo "author=$GITHUB_ACTOR" >> $GITHUB_OUTPUT echo "url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT - # Notify telegram - - uses: yanzay/notify-telegram@v0.1.0 - if: ${{ success() && !contains(needs.*.result, 'failure') }} + - name: Notify Telegram (success) + if: ${{ success() && !contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ✅ success (${{ steps.extract_git_ref.outputs.branch }}) (v${{ needs.prepare.outputs.version }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} - - uses: yanzay/notify-telegram@v0.1.0 + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '🚀 Released: ' + link-url: ${{ github.event.head_commit.url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: 'v${{ needs.prepare.outputs.version }}' + suffix: ' by ${{ steps.extract_git_ref.outputs.author }}' + - name: Notify Telegram (failure) if: ${{ failure() || contains(needs.*.result, 'failure') }} continue-on-error: true + uses: simple-container-com/actions/notify-telegram@main with: - chat: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} - token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} - status: ❗ failure (${{ steps.extract_git_ref.outputs.branch }}) - ${{ steps.extract_git_ref.outputs.message }} by ${{ steps.extract_git_ref.outputs.author }} + chat-id: ${{ needs.build-setup.outputs.cicd-bot-telegram-chat-id }} + token: ${{ needs.build-setup.outputs.cicd-bot-telegram-token }} + text: '❗ Release failed: ' + link-url: ${{ github.event.head_commit.url || format('{0}/{1}/actions/runs/{2}', github.server_url, github.repository, github.run_id) }} + link-text: 'v${{ needs.prepare.outputs.version }}' + suffix: ' by ${{ steps.extract_git_ref.outputs.author }}' - name: Build failed due to previously failed steps id: fail_if_needed diff --git a/.github/workflows/security-scan-comment.yml b/.github/workflows/security-scan-comment.yml new file mode 100644 index 00000000..ddcf0924 --- /dev/null +++ b/.github/workflows/security-scan-comment.yml @@ -0,0 +1,15 @@ +name: Security Scan Comment +on: + workflow_run: + workflows: ["Security Scan"] + types: [completed] +permissions: + pull-requests: write + actions: read +jobs: + comment: + if: github.event.workflow_run.event == 'pull_request' + uses: simple-container-com/actions/.github/workflows/security-scan-comment.yml@main + permissions: + pull-requests: write + actions: read diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 00000000..a25d1cb1 --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,27 @@ +name: Security Scan +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: +permissions: + contents: read +jobs: + security: + uses: simple-container-com/actions/.github/workflows/security-scan.yml@main + permissions: + contents: read + with: + # File-specific path excludes for fixtures/examples that intentionally + # contain placeholder credentials in formats the scanner detects (raw + # OpenSSH key bodies, GCP service-account JSON examples). Each line is + # a TruffleHog Go regex, substring-matched against the full path. + # Source-level placeholder replacements are preferred and have already + # been applied for ~25 docs/test URIs in this PR. + secret-scan-extra-excludes: | + docs/docs/examples/.*/secrets\.yaml + docs/docs/examples/secrets/.*/README\.md + docs/docs/guides/parent-gcp-gke-autopilot\.md + pkg/api/secrets/testdata/repo/ + pkg/provisioner/testdata/ diff --git a/.github/workflows/semgrep-comment.yml b/.github/workflows/semgrep-comment.yml new file mode 100644 index 00000000..9b524ad7 --- /dev/null +++ b/.github/workflows/semgrep-comment.yml @@ -0,0 +1,15 @@ +name: Semgrep Comment +on: + workflow_run: + workflows: ["Semgrep"] + types: [completed] +permissions: + pull-requests: write + actions: read +jobs: + comment: + if: github.event.workflow_run.event == 'pull_request' + uses: simple-container-com/actions/.github/workflows/semgrep-comment.yml@main + permissions: + pull-requests: write + actions: read diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 00000000..468f6beb --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,14 @@ +name: Semgrep +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: +permissions: + contents: read +jobs: + semgrep: + uses: simple-container-com/actions/.github/workflows/semgrep.yml@main + permissions: + contents: read diff --git a/.github/workflows/simple-forge.yml b/.github/workflows/simple-forge.yml index 0af2c70f..43b9135f 100644 --- a/.github/workflows/simple-forge.yml +++ b/.github/workflows/simple-forge.yml @@ -44,7 +44,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} fetch-depth: 0 @@ -55,7 +55,7 @@ jobs: go-version: '1.25' - name: Install welder - run: curl -s "https://welder.simple-container.com/welder.sh" | bash + uses: simple-container-com/actions/install-welder@main - name: Run Simple Forge uses: simple-container-com/forge-action/.github/actions/dockerless@v1 diff --git a/docs/design/archive/ai-assistant/bmad/PROTOTYPE_EXAMPLES.md b/docs/design/archive/ai-assistant/bmad/PROTOTYPE_EXAMPLES.md index b959b1c2..26d0b8ae 100644 --- a/docs/design/archive/ai-assistant/bmad/PROTOTYPE_EXAMPLES.md +++ b/docs/design/archive/ai-assistant/bmad/PROTOTYPE_EXAMPLES.md @@ -54,7 +54,7 @@ User: "Yes, let's do it!" "Excellent! I need these secure values: 1. MongoDB connection string (for database access) - Example: mongodb+srv://user:pass@cluster.mongodb.net/dbname + Example: mongodb+srv://:@.example.com/ 2. JWT secret key (for token signing) Example: your-256-bit-secret-key diff --git a/docs/design/archive/cloud-api/08-deployment-architecture.md b/docs/design/archive/cloud-api/08-deployment-architecture.md index 01ac72bd..261d98de 100644 --- a/docs/design/archive/cloud-api/08-deployment-architecture.md +++ b/docs/design/archive/cloud-api/08-deployment-architecture.md @@ -259,7 +259,7 @@ values: aws-secret-key: your-aws-secret-key-here # Application secrets for deployment - MONGODB_CONNECTION_STRING: mongodb+srv://user:pass@cluster.mongodb.net/db + MONGODB_CONNECTION_STRING: mongodb+srv://:@.example.com/ REDIS_URL: redis://redis-cluster:6379 JWT_SECRET: your-jwt-secret-key diff --git a/docs/design/archive/resources-adoption/COMPUTE_PROCESSORS_ADOPTION.md b/docs/design/archive/resources-adoption/COMPUTE_PROCESSORS_ADOPTION.md index b02a7d4c..a4712c4a 100644 --- a/docs/design/archive/resources-adoption/COMPUTE_PROCESSORS_ADOPTION.md +++ b/docs/design/archive/resources-adoption/COMPUTE_PROCESSORS_ADOPTION.md @@ -20,7 +20,7 @@ graph TD ### **Current Output Example** (Provisioned PostgreSQL) ```bash # What SC currently generates for provisioned PostgreSQL -export DATABASE_URL="postgresql://sc_user:auto_generated_password@10.1.2.3:5432/app_db" +export DATABASE_URL="postgresql://:@:5432/app_db" export POSTGRES_HOST="10.1.2.3" export POSTGRES_PORT="5432" export POSTGRES_USER="sc_user" @@ -579,7 +579,7 @@ func (r *ResourceResolver) ResolveResourceReference(resourceRef string) (string, #### **Adopted PostgreSQL Output** ```bash # Generated for adopted PostgreSQL (existing production database) -export DATABASE_URL="postgresql://acme_app:existing_password@10.1.0.5:5432/acme_production?sslmode=require" +export DATABASE_URL="postgresql://:@:5432/acme_production?sslmode=require" export POSTGRES_HOST="10.1.0.5" export POSTGRES_PORT="5432" export POSTGRES_USER="acme_app" @@ -592,7 +592,7 @@ export POSTGRES_CA_CERT="-----BEGIN CERTIFICATE-----\nMIIDbT..." #### **Provisioned PostgreSQL Output** ```bash # Generated for SC-provisioned PostgreSQL (new analytics database) -export DATABASE_URL="postgresql://sc_analytics_user:auto_generated_pass@10.1.0.8:5432/analytics?sslmode=require" +export DATABASE_URL="postgresql://:@:5432/analytics?sslmode=require" export POSTGRES_HOST="10.1.0.8" export POSTGRES_PORT="5432" export POSTGRES_USER="sc_analytics_user" @@ -620,7 +620,7 @@ mongodb-cluster: #### **MongoDB Compute Processor Output** ```bash # Generated environment variables (adopted MongoDB Atlas) -export MONGODB_URI="mongodb+srv://acme_user:existing_pass@acme-production.mongodb.net/acme_db?retryWrites=true&w=majority" +export MONGODB_URI="mongodb+srv://:@.example.com/?retryWrites=true&w=majority" export MONGO_HOST="acme-production.mongodb.net" export MONGO_PORT="27017" export MONGO_USER="acme_user" @@ -723,10 +723,10 @@ stacks: #### **Runtime Environment** (Generated by compute processors) ```bash # What the sample-app container receives at runtime -DATABASE_URL="postgresql://acme_app:prod_pass@10.1.0.5:5432/acme_production" -MONGO_URL="mongodb+srv://acme_user:atlas_pass@acme-prod.mongodb.net/acme_db" +DATABASE_URL="postgresql://:@:5432/acme_production" +MONGO_URL="mongodb+srv://:@.example.com/" REDIS_URL="redis://:redis_auth@10.1.0.6:6379" -ANALYTICS_DB="postgresql://sc_analytics:auto_gen_pass@10.1.0.8:5432/analytics" +ANALYTICS_DB="postgresql://:@:5432/analytics" METRICS_STORE="redis://:auto_gen_auth@10.1.0.9:6379" ``` diff --git a/docs/design/archive/resources-adoption/DEPLOYMENT_FLOW_VALIDATION.md b/docs/design/archive/resources-adoption/DEPLOYMENT_FLOW_VALIDATION.md index f1016cc9..e2c3ad9c 100644 --- a/docs/design/archive/resources-adoption/DEPLOYMENT_FLOW_VALIDATION.md +++ b/docs/design/archive/resources-adoption/DEPLOYMENT_FLOW_VALIDATION.md @@ -241,14 +241,14 @@ pulumi stack output service-a-mongo-user **Environment Variables Received**: ```bash # PostgreSQL (from adopted resource) -DATABASE_URL="postgresql://service-a:generated_password_123@10.1.0.5:5432/service-a" +DATABASE_URL="postgresql://:@:5432/service-a" POSTGRES_HOST="10.1.0.5" POSTGRES_PORT="5432" POSTGRES_USER="service-a" POSTGRES_PASSWORD="generated_password_123" # MongoDB (from adopted resource) -MONGO_URI="mongodb+srv://service-a:generated_password_456@acme-staging.mongodb.net/service-a" +MONGO_URI="mongodb+srv://:@.example.com/" MONGO_USER="service-a" MONGO_PASSWORD="generated_password_456" @@ -301,11 +301,11 @@ sc deploy -s service-b -e staging **Validation**: ```sql -- From service-a pod, try to access service-b database -psql postgresql://service-a:password@host/service-b -c "SELECT 1;" +psql postgresql://:@/service-b -c "SELECT 1;" -- Expected: ERROR: permission denied for database service-b -- Verify service-b has its own credentials -psql postgresql://service-b:password@host/service-b -c "SELECT 1;" +psql postgresql://:@/service-b -c "SELECT 1;" -- Expected: Success ``` diff --git a/docs/design/cloud-api/08-deployment-architecture.md b/docs/design/cloud-api/08-deployment-architecture.md index 01ac72bd..261d98de 100644 --- a/docs/design/cloud-api/08-deployment-architecture.md +++ b/docs/design/cloud-api/08-deployment-architecture.md @@ -259,7 +259,7 @@ values: aws-secret-key: your-aws-secret-key-here # Application secrets for deployment - MONGODB_CONNECTION_STRING: mongodb+srv://user:pass@cluster.mongodb.net/db + MONGODB_CONNECTION_STRING: mongodb+srv://:@.example.com/ REDIS_URL: redis://redis-cluster:6379 JWT_SECRET: your-jwt-secret-key diff --git a/docs/docs/ai-assistant/developer-mode.md b/docs/docs/ai-assistant/developer-mode.md index e204cb52..bac9c851 100644 --- a/docs/docs/ai-assistant/developer-mode.md +++ b/docs/docs/ai-assistant/developer-mode.md @@ -115,7 +115,7 @@ services: - "3000:3000" environment: - NODE_ENV=development - - DATABASE_URL=postgresql://user:pass@postgres:5432/myapp + - DATABASE_URL=postgresql://:@:5432/myapp - REDIS_URL=redis://redis:6379 depends_on: - postgres @@ -129,7 +129,7 @@ services: command: npm run worker environment: - NODE_ENV=development - - DATABASE_URL=postgresql://user:pass@postgres:5432/myapp + - DATABASE_URL=postgresql://:@:5432/myapp - REDIS_URL=redis://redis:6379 depends_on: - postgres diff --git a/docs/docs/ai-assistant/examples/nodejs-express-api.md b/docs/docs/ai-assistant/examples/nodejs-express-api.md index 51cc398d..75ffcaf8 100644 --- a/docs/docs/ai-assistant/examples/nodejs-express-api.md +++ b/docs/docs/ai-assistant/examples/nodejs-express-api.md @@ -223,7 +223,7 @@ services: environment: - NODE_ENV=development - PORT=3000 - - DATABASE_URL=postgresql://taskuser:taskpass@postgres:5432/taskdb + - DATABASE_URL=postgresql://:@:5432/taskdb - REDIS_URL=redis://redis:6379 - JWT_SECRET=dev-jwt-secret-key-123 depends_on: diff --git a/docs/docs/ai-assistant/usage-examples.md b/docs/docs/ai-assistant/usage-examples.md index 92e7baa9..77a200e7 100644 --- a/docs/docs/ai-assistant/usage-examples.md +++ b/docs/docs/ai-assistant/usage-examples.md @@ -315,7 +315,7 @@ services: environment: - GO_ENV=development - PORT=8080 - - DATABASE_URL=postgres://user:password@db:5432/myapp + - DATABASE_URL=postgres://:@:5432/myapp volumes: - .:/app depends_on: diff --git a/docs/docs/examples/kubernetes-affinity/multi-tier-node-isolation/secrets.yaml b/docs/docs/examples/kubernetes-affinity/multi-tier-node-isolation/secrets.yaml index f6cef886..741b1a0e 100644 --- a/docs/docs/examples/kubernetes-affinity/multi-tier-node-isolation/secrets.yaml +++ b/docs/docs/examples/kubernetes-affinity/multi-tier-node-isolation/secrets.yaml @@ -13,8 +13,8 @@ auth: "project_id": "mycompany-production-12345", "private_key_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8Q7HgL...\n-----END PRIVATE KEY-----\n", - "client_email": "mycompany-service@mycompany-production-12345.iam.gserviceaccount.com", - "client_id": "123456789012345678901", + "client_email": "@.iam.gserviceaccount.com", + "client_id": "", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", @@ -36,7 +36,7 @@ values: redis-password: "R3d1s!Auth789" # JWT and encryption keys - jwt-secret: "jwt-secret-key-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + jwt-secret: "jwt-secret-" encryption-key: "32-char-encryption-key-123456789012" # External API keys diff --git a/docs/docs/examples/kubernetes-vpa/.sc/stacks/infrastructure/secrets.yaml b/docs/docs/examples/kubernetes-vpa/.sc/stacks/infrastructure/secrets.yaml index 1f230c64..19b61fb7 100644 --- a/docs/docs/examples/kubernetes-vpa/.sc/stacks/infrastructure/secrets.yaml +++ b/docs/docs/examples/kubernetes-vpa/.sc/stacks/infrastructure/secrets.yaml @@ -15,8 +15,8 @@ auth: "project_id": "my-gcp-project-12345", "private_key_id": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8Q7HgL...\n-----END PRIVATE KEY-----\n", - "client_email": "vpa-demo-service@my-gcp-project-12345.iam.gserviceaccount.com", - "client_id": "123456789012345678901", + "client_email": "@.iam.gserviceaccount.com", + "client_id": "", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", @@ -31,7 +31,7 @@ values: mongodb-atlas-private-key: "12345678-1234-1234-1234-123456789012" # Application secrets for VPA demo - app-jwt-secret: "jwt-secret-key-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6" + app-jwt-secret: "jwt-secret-" app-encryption-key: "32-char-encryption-key-123456789012" # Note: In production, these values should be: diff --git a/docs/docs/examples/resource-adoption/secrets.yaml b/docs/docs/examples/resource-adoption/secrets.yaml index 8f5964d4..4aeb237f 100644 --- a/docs/docs/examples/resource-adoption/secrets.yaml +++ b/docs/docs/examples/resource-adoption/secrets.yaml @@ -32,7 +32,7 @@ auth: "project_id": "your-production-gcp-project", "private_key_id": "your-private-key-id", "private_key": "-----BEGIN PRIVATE KEY-----\nyour-private-key-content\n-----END PRIVATE KEY-----\n", - "client_email": "your-service-account@your-production-gcp-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-client-id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", @@ -52,7 +52,7 @@ auth: "project_id": "your-staging-gcp-project", "private_key_id": "your-private-key-id", "private_key": "-----BEGIN PRIVATE KEY-----\nyour-private-key-content\n-----END PRIVATE KEY-----\n", - "client_email": "your-service-account@your-staging-gcp-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-client-id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", @@ -72,7 +72,7 @@ auth: "project_id": "your-production-gcp-project", "private_key_id": "your-private-key-id", "private_key": "-----BEGIN PRIVATE KEY-----\nyour-private-key-content\n-----END PRIVATE KEY-----\n", - "client_email": "your-service-account@your-production-gcp-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-client-id", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", diff --git a/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/README.md b/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/README.md index 7b4fd00f..78960362 100644 --- a/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/README.md +++ b/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/README.md @@ -76,12 +76,12 @@ gcloud iam service-accounts create simple-container-deploy-bot \ # Grant necessary permissions gcloud projects add-iam-policy-binding your-project-id \ - --member="serviceAccount:simple-container-deploy-bot@your-project-id.iam.gserviceaccount.com" \ + --member="serviceAccount:@.iam.gserviceaccount.com" \ --role="roles/editor" # Create and download service account key gcloud iam service-accounts keys create service-account.json \ - --iam-account=simple-container-deploy-bot@your-project-id.iam.gserviceaccount.com + --iam-account=@.iam.gserviceaccount.com ``` #### Configure Multiple Environments diff --git a/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/secrets.yaml b/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/secrets.yaml index 4e55eaff..4a1f7350 100644 --- a/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/secrets.yaml +++ b/docs/docs/examples/secrets/gcp-auth-cloudflare-mongodb-discord-telegram/secrets.yaml @@ -10,7 +10,7 @@ auth: "project_id": "your-gcp-project-id", "private_key_id": "your-private-key-id-here", "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-ACTUAL-PRIVATE-KEY-CONTENT-GOES-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "your-service-account@your-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-client-id-here", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", @@ -28,7 +28,7 @@ auth: "project_id": "your-staging-gcp-project-id", "private_key_id": "your-staging-private-key-id-here", "private_key": "-----BEGIN PRIVATE KEY-----\nYOUR-ACTUAL-STAGING-PRIVATE-KEY-CONTENT-GOES-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "your-staging-service-account@your-staging-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-staging-client-id-here", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", diff --git a/docs/docs/examples/secrets/kube-and-gcp-auth/README.md b/docs/docs/examples/secrets/kube-and-gcp-auth/README.md index 60a8340b..8e10ca42 100644 --- a/docs/docs/examples/secrets/kube-and-gcp-auth/README.md +++ b/docs/docs/examples/secrets/kube-and-gcp-auth/README.md @@ -26,8 +26,8 @@ auth: "project_id": "project-id", "private_key_id": "...", "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", - "client_email": "deployer-bot@ai-asia-382012.iam.gserviceaccount.com", - "client_id": "104019626917208012368", + "client_email": "@.iam.gserviceaccount.com", + "client_id": "", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", diff --git a/docs/docs/examples/secrets/kube-and-gcp-auth/secrets.yaml b/docs/docs/examples/secrets/kube-and-gcp-auth/secrets.yaml index 2af677df..f5b41ed7 100644 --- a/docs/docs/examples/secrets/kube-and-gcp-auth/secrets.yaml +++ b/docs/docs/examples/secrets/kube-and-gcp-auth/secrets.yaml @@ -10,7 +10,7 @@ auth: "project_id": "your-gcp-project-id", "private_key_id": "your-private-key-id-here", "private_key": "-----BEGIN PRIVATE KEY-----\\nYOUR-ACTUAL-PRIVATE-KEY-CONTENT-GOES-HERE\n-----END PRIVATE KEY-----\n", - "client_email": "your-service-account@your-project.iam.gserviceaccount.com", + "client_email": "@.iam.gserviceaccount.com", "client_id": "your-client-id-here", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", diff --git a/docs/docs/guides/parent-gcp-gke-autopilot.md b/docs/docs/guides/parent-gcp-gke-autopilot.md index 68456786..6a2f1536 100644 --- a/docs/docs/guides/parent-gcp-gke-autopilot.md +++ b/docs/docs/guides/parent-gcp-gke-autopilot.md @@ -50,10 +50,10 @@ auth: { "type": "service_account", "project_id": "my-gcp-project-id", - "private_key_id": "60bb42f229bc21f6d303b5967b6cd59265cb316d", + "private_key_id": "", "private_key": "-----BEGIN PRIVATE KEY-----\nBLABLABLA\n-----END PRIVATE KEY-----\n", - "client_email": "deploy-bot@my-gcp-project-id.iam.gserviceaccount.com", - "client_id": "2387492479284792742398427", + "client_email": "@.iam.gserviceaccount.com", + "client_id": "", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", diff --git a/docs/docs/guides/secrets-management.md b/docs/docs/guides/secrets-management.md index 91d376e4..590caa42 100644 --- a/docs/docs/guides/secrets-management.md +++ b/docs/docs/guides/secrets-management.md @@ -622,7 +622,7 @@ env: ```yaml # .sc/stacks/your-parent-stack/secrets.yaml values: - database-url: "postgresql://user:pass@host:5432/db" + database-url: "postgresql://:@:5432/db" api-key: "your-secret-api-key-here" ``` diff --git a/docs/docs/reference/supported-resources.md b/docs/docs/reference/supported-resources.md index 4cca3f70..a92f6825 100644 --- a/docs/docs/reference/supported-resources.md +++ b/docs/docs/reference/supported-resources.md @@ -436,7 +436,7 @@ auth: values: # Exact literal values - NO placeholders processed in secrets.yaml - DATABASE_URL: "postgresql://user:pass@host:5432/db" + DATABASE_URL: "postgresql://:@:5432/db" API_KEY: "your-secret-api-key-here" ``` @@ -462,7 +462,7 @@ values: # Exact literal values - NO placeholders processed in secrets.yaml DATABASE_PASSWORD: "mySecurePassword123" API_KEY: "sk-1234567890abcdef" - CLOUDFLARE_API_TOKEN: "gEYRal5hQm4XJWE5WROP6DAEsdb3NxOgQUcpKjzB" + CLOUDFLARE_API_TOKEN: "" ``` ### **Provisioner Configuration** (goes to `provisioner` section in `server.yaml`) diff --git a/docs/product-manager/container-security/acceptance-criteria.md b/docs/product-manager/container-security/acceptance-criteria.md index c984ab10..d0c7acba 100644 --- a/docs/product-manager/container-security/acceptance-criteria.md +++ b/docs/product-manager/container-security/acceptance-criteria.md @@ -59,7 +59,7 @@ Given: Running in GitHub Actions with id-token: write permission When: Workflow executes `sc deploy -s mystack -e production` Then: - OIDC token is automatically obtained from GitHub Actions - - Image is signed with identity: https://github.com/myorg/myrepo/.github/workflows/deploy.yml@refs/heads/main + - Image is signed with identity: https://///.github/workflows/deploy.yml@refs/heads/main - Signature includes Rekor transparency log entry - Signature can be verified with: cosign verify --certificate-identity-regexp "^https://github.com/myorg/.*$" ``` @@ -303,8 +303,8 @@ Then: - Provenance follows SLSA v1.0 schema - Provenance includes: - buildType: "https://github.com/simple-container-com/api@v1" - - builder.id: "https://github.com/myorg/myrepo/.github/workflows/deploy.yml@refs/heads/main" - - invocation.configSource.uri: "git+https://github.com/myorg/myrepo@refs/heads/main" + - builder.id: "https://///.github/workflows/deploy.yml@refs/heads/main" + - invocation.configSource.uri: "git+https:////@refs/heads/main" - invocation.configSource.digest.sha1: "" ``` @@ -313,21 +313,21 @@ Then: **Test Case:** TC-3.2.1 - GitHub Actions Detection ```yaml Given: Running in GitHub Actions - And: GITHUB_REPOSITORY=myorg/myrepo + And: GITHUB_REPOSITORY=/ And: GITHUB_WORKFLOW=Deploy When: Provenance is generated Then: - - builder.id: "https://github.com/myorg/myrepo/.github/workflows/Deploy@refs/heads/main" + - builder.id: "https://///.github/workflows/Deploy@refs/heads/main" ``` **Test Case:** TC-3.2.2 - GitLab CI Detection ```yaml Given: Running in GitLab CI - And: CI_PROJECT_PATH=myorg/myrepo - And: CI_PIPELINE_URL=https://gitlab.com/myorg/myrepo/-/pipelines/12345 + And: CI_PROJECT_PATH=/ + And: CI_PIPELINE_URL=https://///-/pipelines/12345 When: Provenance is generated Then: - - builder.id: "https://gitlab.com/myorg/myrepo/-/pipelines/12345" + - builder.id: "https://///-/pipelines/12345" ``` ### AC-3.3: Source Materials Inclusion @@ -339,7 +339,7 @@ Given: security.provenance.metadata.includeMaterials=true When: Provenance is generated Then: - materials array includes: - - uri: "git+https://github.com/myorg/myrepo@refs/heads/main" + - uri: "git+https:////@refs/heads/main" - digest.sha1: "abc123" ``` diff --git a/pkg/clouds/docker/types_test.go b/pkg/clouds/docker/types_test.go index 865e68ed..f0baf802 100644 --- a/pkg/clouds/docker/types_test.go +++ b/pkg/clouds/docker/types_test.go @@ -18,7 +18,7 @@ func Test_GenerateImagePullSecret(t *testing.T) { }{ { name: "happy-path", - expectResult: "eyJhdXRocyI6eyJkb2NrZXIuc2ltcGxlLWNvbnRhaW5lci5jb20iOnsiYXV0aCI6ImRYTmxjanB3WVhOemQyOXlaQT09IiwidXNlcm5hbWUiOiJ1c2VyIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9fX0=", + expectResult: "eyJhdXRocyI6eyJkb2NrZXIuc2ltcGxlLWNvbnRhaW5lci5jb20iOnsiYXV0aCI6ImRYTmxjanB3WVhOemQyOXlaQT09IiwidXNlcm5hbWUiOiJ1c2VyIiwicGFzc3dvcmQiOiJwYXNzd29yZCJ9fX0=", // trufflehog:ignore (nested base64 of fake user:password test fixture) creds: RegistryCredentials{ DockerRegistryURL: lo.ToPtr("docker.simple-container.com"), DockerRegistryUsername: lo.ToPtr("user"), diff --git a/pkg/clouds/pulumi/kubernetes/simple_container_advanced_test.go b/pkg/clouds/pulumi/kubernetes/simple_container_advanced_test.go index 3fceff58..6915c157 100644 --- a/pkg/clouds/pulumi/kubernetes/simple_container_advanced_test.go +++ b/pkg/clouds/pulumi/kubernetes/simple_container_advanced_test.go @@ -167,7 +167,7 @@ func TestSimpleContainer_ComplexVolumeConfiguration(t *testing.T) { // Secret environment variables SecretEnvs: map[string]string{ - "DATABASE_URL": "postgresql://user:pass@db:5432/mydb", + "DATABASE_URL": "postgresql://:@:5432/mydb", "API_KEY": "super-secret-api-key", "ENCRYPTION_SECRET": "encryption-key-123", }, diff --git a/pkg/clouds/pulumi/mongodb/util_test.go b/pkg/clouds/pulumi/mongodb/util_test.go index 7535b8fd..4b92da1c 100644 --- a/pkg/clouds/pulumi/mongodb/util_test.go +++ b/pkg/clouds/pulumi/mongodb/util_test.go @@ -1,6 +1,9 @@ package mongodb -import "testing" +import ( + "net/url" + "testing" +) func Test_appendUserPasswordToMongoUri(t *testing.T) { type args struct { @@ -12,33 +15,56 @@ func Test_appendUserPasswordToMongoUri(t *testing.T) { tests := []struct { name string args args - want string }{ { name: "happy-path", args: args{ - mongoUri: "mongodb://ac-gvptdqa-shard-00-00.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-01.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-02.qo081kw.mongodb.net:27017/?param1=value1¶m2=value2", + mongoUri: "mongodb://shard-00-00.example.com:27017,shard-00-01.example.com:27017,shard-00-02.example.com:27017/?param1=value1¶m2=value2", user: "test-user", password: "test-password", dbName: "test-db", }, - want: "mongodb://test-user:test-password@ac-gvptdqa-shard-00-00.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-01.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-02.qo081kw.mongodb.net:27017/test-db?param1=value1¶m2=value2", }, { name: "happy-path mongodb+srv", args: args{ - mongoUri: "mongodb+srv://ac-gvptdqa-shard-00-00.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-01.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-02.qo081kw.mongodb.net:27017/?param1=value1¶m2=value2", + mongoUri: "mongodb+srv://shard-00-00.example.com:27017,shard-00-01.example.com:27017,shard-00-02.example.com:27017/?param1=value1¶m2=value2", user: "test-user", password: "test-password", dbName: "test-db", }, - want: "mongodb+srv://test-user:test-password@ac-gvptdqa-shard-00-00.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-01.qo081kw.mongodb.net:27017,ac-gvptdqa-shard-00-02.qo081kw.mongodb.net:27017/test-db?param1=value1¶m2=value2", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := AppendUserPasswordAndDBToMongoUri(tt.args.mongoUri, tt.args.user, tt.args.password, tt.args.dbName); got != tt.want { - t.Errorf("AppendUserPasswordAndDBToMongoUri() = %v, want %v", got, tt.want) + got := AppendUserPasswordAndDBToMongoUri(tt.args.mongoUri, tt.args.user, tt.args.password, tt.args.dbName) + + gotURL, err := url.Parse(got) + if err != nil { + t.Fatalf("AppendUserPasswordAndDBToMongoUri returned a value that failed to parse: %v", err) + } + inputURL, err := url.Parse(tt.args.mongoUri) + if err != nil { + t.Fatalf("test setup: input URI did not parse: %v", err) + } + + if gotURL.Scheme != inputURL.Scheme { + t.Errorf("scheme mutated: got %q, want %q", gotURL.Scheme, inputURL.Scheme) + } + if gotURL.Host != inputURL.Host { + t.Errorf("host mutated: got %q, want %q", gotURL.Host, inputURL.Host) + } + if gotURL.RawQuery != inputURL.RawQuery { + t.Errorf("query mutated: got %q, want %q", gotURL.RawQuery, inputURL.RawQuery) + } + if got, want := gotURL.User.Username(), tt.args.user; got != want { + t.Errorf("username: got %q, want %q", got, want) + } + if pw, ok := gotURL.User.Password(); !ok || pw != tt.args.password { + t.Errorf("password: got %q (set=%v), want %q", pw, ok, tt.args.password) + } + if got, want := gotURL.Path, "/"+tt.args.dbName; got != want { + t.Errorf("path: got %q, want %q", got, want) } }) } diff --git a/sc.sh b/sc.sh index a37f90fb..5570bb1d 100755 --- a/sc.sh +++ b/sc.sh @@ -520,6 +520,7 @@ if ! [ -x "$(command -v pulumi)" ]; then echo "🔧 Pulumi not found, installing..." if [[ "$PLATFORM" == "linux" ]]; then echo "📦 Installing Pulumi for Linux..." + # nosemgrep: shell-curl-pipe-to-shell -- pulumi's documented upstream installer (https://www.pulumi.com/docs/install/), invoked from this end-user installer running on the user's own machine, not in CI if curl -fsSL https://get.pulumi.com | sh; then echo "✅ Pulumi installed successfully" else diff --git a/welder.yaml b/welder.yaml index e26d7075..9f467182 100644 --- a/welder.yaml +++ b/welder.yaml @@ -112,12 +112,11 @@ tasks: - cp ${project:root}/.sc/stacks/dist/site/* ${project:root}/.sc/stacks/dist/bundle/ docker-login: runOn: host + # `sc` is provisioned on the runner by the install-sc composite action + # before welder is invoked (see .github/workflows/*.yaml). script: - - |- - bash -c ' - bash <(curl -Ls "https://dist.simple-container.com/sc.sh") secrets reveal - sc stack secret-get -s dist dockerhub-cicd-token | docker login --username simplecontainer --password-stdin - ' + - sc secrets reveal + - sc stack secret-get -s dist dockerhub-cicd-token | docker login --username simplecontainer --password-stdin build-cloud-helpers: runOn: host script: