Skip to content

Commit 83bff83

Browse files
committed
ci: add automated hackage publishing and streamline release workflow
Implements comprehensive automated publishing to Hackage with proper validation and error handling, while consolidating the CI/CD pipeline for more efficient releases. Publishing improvements: - Switch from curl-based uploads to native cabal upload command - Configure credentials via cabal config file instead of curl auth - Add automatic version extraction from cabal file - Implement duplicate upload detection to prevent failures - Support both candidate and production publishing modes Release workflow enhancements: - Merge separate publish job into release job for efficiency - Add write permissions for automated release creation - Support both tag-based and manual release triggers - Switch to softprops/action-gh-release for robust releases - Remove redundant artifact upload steps Configuration changes: - Add HACKAGE_USERNAME and HACKAGE_PASSWORD secret configuration - Install Haskell toolchain in release job for cabal commands This change significantly simplifies the deployment pipeline while adding proper error handling and validation to prevent common publishing issues like duplicate uploads or missing credentials.
1 parent 9eb74d4 commit 83bff83

File tree

1 file changed

+36
-57
lines changed

1 file changed

+36
-57
lines changed

.github/workflows/haskell.yml

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ on:
1414
schedule:
1515
- cron: '0 0 */6 * *'
1616

17+
permissions:
18+
contents: write
19+
1720
jobs:
1821
build:
1922
runs-on: ${{ matrix.sys.os }}
@@ -185,14 +188,20 @@ jobs:
185188
needs: [build, check]
186189
runs-on: ubuntu-latest
187190

188-
if: ${{ needs.check.outputs.tag != '' }}
191+
if: ${{ needs.check.outputs.tag != '' || startsWith(github.ref, 'refs/tags/v') }}
189192

190193
outputs:
191194
upload_url: ${{ steps.create_release.outputs.upload_url }}
192195

193196
steps:
194197
- uses: actions/checkout@v3
195198

199+
- name: Install Haskell
200+
uses: input-output-hk/actions/haskell@latest
201+
with:
202+
ghc-version: '9.12'
203+
cabal-version: '3.14'
204+
196205
- name: Create source distribution
197206
run: |
198207
PROJECT_DIR="$PWD"
@@ -202,6 +211,28 @@ jobs:
202211
cabal v2-sdist -o $PROJECT_DIR/build/sdist
203212
done;
204213
214+
- name: Publish to hackage
215+
env:
216+
HACKAGE_USERNAME: ${{ secrets.HACKAGE_USER }}
217+
HACKAGE_PASSWORD: ${{ secrets.HACKAGE_PASS }}
218+
run: |
219+
# Ensure .cabal directory exists
220+
mkdir -p ~/.cabal
221+
222+
# Configure cabal with Hackage credentials
223+
cat > ~/.cabal/config <<EOF
224+
repository hackage.haskell.org
225+
url: http://hackage.haskell.org/
226+
username: $HACKAGE_USERNAME
227+
password: $HACKAGE_PASSWORD
228+
EOF
229+
230+
# Upload as candidate (without --publish flag)
231+
for PACKAGE_TARBALL in $(find ./build/sdist/ -name "*.tar.gz"); do
232+
echo "Uploading $PACKAGE_TARBALL as candidate"
233+
cabal upload --username="$HACKAGE_USERNAME" --password="$HACKAGE_PASSWORD" "$PACKAGE_TARBALL" || echo "Upload failed (package may already exist)"
234+
done
235+
205236
- name: Generate Changelog
206237
run: |
207238
git fetch --unshallow
@@ -216,62 +247,10 @@ jobs:
216247
217248
- name: Create Release
218249
id: create_release
219-
uses: actions/create-release@v1
220-
env:
221-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
250+
uses: softprops/action-gh-release@v2
222251
with:
223-
tag_name: ${{ needs.check.outputs.tag }}
224-
release_name: Release ${{ needs.check.outputs.tag }}
252+
tag_name: ${{ needs.check.outputs.tag != '' && needs.check.outputs.tag || github.ref_name }}
253+
name: Release ${{ needs.check.outputs.tag != '' && needs.check.outputs.tag || github.ref_name }}
254+
body_path: changelog.txt
225255
draft: false
226256
prerelease: false
227-
body_path: changelog.txt
228-
229-
publish:
230-
needs: [build, release]
231-
232-
runs-on: ${{ matrix.os }}
233-
234-
if: ${{ needs.check.outputs.tag != '' }}
235-
236-
strategy:
237-
fail-fast: false
238-
matrix:
239-
ghc: ["8.10.4"]
240-
os: [ubuntu-latest, macos-latest]
241-
242-
steps:
243-
- uses: actions/download-artifact@v4
244-
id: download_artifact
245-
with:
246-
name: artifacts-${{ runner.OS }}-${{ matrix.ghc }}.tar.gz
247-
path: .
248-
249-
- name: Compute axes
250-
id: axes
251-
run: |
252-
case ${{ matrix.os }} in
253-
ubuntu-*) os="linux" ;;
254-
macos-*) os="darwin" ;;
255-
windows-*) os="windows" ;;
256-
*) exit 1 ;; # error
257-
esac
258-
arch_os="$(uname -m)-$os"
259-
echo "::set-output name=arch_os::$arch_os"
260-
261-
- name: Upload Artifacts to Release
262-
uses: softprops/action-gh-release@v1
263-
if: startsWith(github.ref, 'refs/tags/')
264-
env:
265-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
266-
with:
267-
files: artifacts-${{ runner.OS }}-${{ matrix.ghc }}.tar.gz
268-
269-
- name: Upload Artifacts to Release
270-
uses: actions/[email protected]
271-
env:
272-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
273-
with:
274-
upload_url: ${{ needs.release.outputs.upload_url }}
275-
asset_path: artifacts-${{ runner.OS }}-${{ matrix.ghc }}.tar.gz
276-
asset_name: artifacts-${{ runner.OS }}-${{ matrix.ghc }}.tar.gz
277-
asset_content_type: application/tar+gzip

0 commit comments

Comments
 (0)